0

背景:


这一切都始于我朋友使用文件编写的程序。

跳过其他细节,我将重点放在真正吸引我注意力的地方。

  1. 文件中有文本需要提取为字符串。
  2. 字符串可以有不同的长度。
  3. 为了实现这一点并且不额外花费一个字节,他使用了动态内存分配。他首先计算了大小,然后用 malloc 创建了一个足够大小的字符串,然后将字符插入到目标字符串中。

这很好,但我倾向于考虑是否有另一种方法可以在没有任何额外字节的情况下将字符存储在字符串中。

我带来了以下程序:

代码:


/* 为简单起见,我在这里使用了另一个字符串“c”而不是文件,需要从中复制数据。将 ch 视为来自 File 的读取字符。

# include <stdio.h>
# include <string.h>

void main()
{
char *s,*p;
char c[4] ="abc";

char q[2] = "";
s=q;

int i;
for(i=0;c[i]!='\0';i++)
{
    char ch = c[i];
    int len = strlen(s);
    char p[len+2];
    strcpy(p,s);
    p[len]=ch;
    p[len+1]='\0';
    printf("%s\n",p);
    s=p;
}
char t[strlen(s)+1];
strcpy(t,s);

printf("%s\n",t);  //EDIT for understanding: If I print s here it prints garbage, 
                          but if I see the value of s through debugger, it gives
                          correct value?
}

理解:


  1. 字符串 p 的作用域是 for 循环,每次迭代我们都会得到它的新定义。
  2. 字符串的起始地址保存到变量 s 中,这就是为什么即使代码超出范围也可以访问内存,这用于在遇到新字符时确定字符串的大小。

问题:


1.如果我上面的理解是正确的,那么就缺少了一些东西。我这样说是因为如果我直接尝试打印 s,它会打印垃圾,而不是 strcpy s 到 t 并打印 t(它给出正确的 O/P)。我不确定这种行为?

2.这个程序有内存损坏的可能吗?

PS:我知道多个 strcpy() 过度杀戮,因此程序没有优化,只是问这个问题来理解这种行为。

4

2 回答 2

1

一旦变量的生命周期结束,编译器就可以自由地重用它认为合适的内存。创建“新” p 时(下一次循环,循环结束后)保留指向“旧” p 的指针根本不能保证有效。我不希望这项工作可靠,新旧 ps 很可能最终会重叠。

无论您使用 strcpy 还是任何其他技术,与简单使用 malloc 以及在必要时偶尔重新分配相比,持续的数据混洗将花费很多。

于 2013-08-06T18:21:27.107 回答
0

In mains 和 p 被定义为指针:char *s, *p 稍后在 for 循环之后,您询问打印 s 并获取垃圾,因为s它是一个指针并且 printf 试图打印该地址,要么使用:printf("%p", s);打印存储在 s 中的地址或printf("%c", *s);打印字符s 所指。

在 for 循环中,您定义了一个名p[len+2]为此定义的变量,它隐藏了main. 一般来说,这是一种不好的做法。你真的是想 1) 定义 p 的第二个版本还是 2) 你想在 p 指向的位置存储信息吗?

如果 1) 将 p 重命名为其他名称,那么您的错误将很明显;if 2)为 p 分配一些存储空间,然后从你的 for 循环中填充它。

希望我理解您的意图,并希望这会有所帮助。

于 2013-08-06T22:49:47.557 回答