您好我很困惑在下面得到解释,有人可以向我解释一下吗?提前谢谢。
#include<stdio.h>
int main(){
char *arr,c;
arr = &c;
arr++;
*arr = 'a';
arr++;
*arr = 'b';
arr++;
*arr = 'c';
arr--;
arr--;
printf("\narr 1 = %c",arr);
printf("\narr 2 = %c",arr[1]);
printf("\narr 3 = %c",arr[2]);
getch();
return 1;
}
输出是:
arr 1 = a
arr 2 = b
arr 3 = c
但如果更改了行:
printf("\narr 1 = %c",arr);
与
printf("\narr 1 = %c",arr[0]);
现在输出是:
arr 1 =
arr 2 = b
arr 3 = c
为什么'a'没有打印出来。?
*对于那些质疑程序编码不好的人...我知道使用这样的指针不是一个好的编码实践,但我的问题是为什么arr [0]不打印任何地方作为arr [1] &安培; arr [2]正在打印分配的内容吗?
答案 0 :(得分:9)
在该计划的第一个版本中,可能发生的是:
c
放在堆栈的某个地址,例如1003(单个字节)。arr
放在堆栈的某个地址,例如1004-1007(四个字节)。arr = &c;
将c
,1003的地址放入arr
。arr++;
向arr
添加一个,因此它现在是1004而不是1003。*arr = 'a';
将'a'
写入arr
指向的地方。现在这是C标准未定义的行为。当arr
设置为&c
时,该位置的对象中只有一个字节,并且C标准不保证在对象外部递增该地址后写入其他位置时会发生什么。 arr
,因此您将'a'
写入arr
的一个字节中。这可怕地改变了arr
中的地址。arr++;
再次递增地址,*arr = 'b';
在某处写'b'
。我们不知道在哪里,因为arr
的价值很低。arr++;
再次递增地址,*arr = 'c';
在某处写'c'
。我们不知道在哪里。arr--;
和arr--;
将地址返回到'a'
写入后的值。printf
调用将arr
中的值传递给要打印的“%c”说明符。 “%c”用于打印字符,但是传递它的arr
是指针。但是,您之前已将'a'
写入指针,因此指针的值在其中一个字节中具有'a'
。printf
的这个实现打印指针值中的一个字节,在这种情况下是您写入{{1}的相同字节}}。所以打印出“a”。 你不能在其他C实现中依赖这种情况。在这种情况下发生这种情况只是因为编译器碰巧将'a'
放在内存中arr
之后的内存中,所以声明c
将*arr = 'a';
写入'a'
。这不会发生在所有C实现中。你得到了“幸运儿”。arr
写入'a'
后,arr
指向某处,但我们不知道在哪里。我们称这个位置为arr
。x
和arr++;
将*arr = 'b';
写入'b'
位置。x+1
和arr++;
将*arr = 'c';
写入'c'
位置。x+2
语句返回arr--;
以指向arr
。因此x
是arr[1]
处的字符,x+1
,'b'
是arr[2]
。将这些传递给要用“%c”打印的printf打印“b”和“c”。在该计划的第二个版本中,当'c'
传递给arr[0]
时:
printf
的值是将arr
写入其中一个字节而形成的值。这是一些“随机”地址,指向我们没有控制的位置。显然,那里有一个0字符,或者其他一些非打印字符,因此,当'a'
传递给arr[0]
时,不会打印任何内容。printf
和arr[1]
打印“b”和“c”,因为代码将arr[2]
和'b'
写入了这些位置。答案 1 :(得分:6)
arr
不等同于arr[0]
,因为arr[0]
取消引用数组。正确的等价物是&arr[0]
。
顺便说一下,你正在做什么调用未定义的行为,因为在递增arr
后,它指向一个无效的内存位置 - 最初它指向一个单个字符,所以你不能假设它之后有什么东西。
答案 2 :(得分:6)
这只是未定义的行为 - arr++; *arr = 'a';
是非法的,因为arr
指向单个char
。任何事情都可能发生。