为什么这个arr [0]不等于arr + 0?

Kun*_*asu 1 c

嗨,我很困惑,得到下面的解释,有人可以解释给我吗?提前致谢.

#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;
    }
Run Code Online (Sandbox Code Playgroud)

输出为:
arr 1 = a
arr 2 = b
arr 3 = c

但如果改变线:

printf("\narr 1 = %c",arr);
Run Code Online (Sandbox Code Playgroud)

printf("\narr 1 = %c",arr[0]);
Run Code Online (Sandbox Code Playgroud)

现在输出为:
arr 1 =  
arr 2 = b
arr 3 = c

为什么'a'没有印刷.?

*对于所有那些质疑程序编码不好的人来说..我知道使用像这样的指针不是一个好的编码实践,但我的问题是为什么arr [0]不打印任何地方,如arr [1]&arr [ 2]是打印分配的内容?

Eri*_*hil 9

在该程序的第一个版本中,可能发生的是:

  • 编译器放在c堆栈的某个地址,比如1003(单个字节).
  • 编译器arr在堆栈上放置一些地址,比如说1004-1007(四个字节).
  • 该声明arr = &c;将地址c1003放入arr.
  • 该语句arr++;添加了一个arr,所以它现在是1004而不是1003.
  • 声明*arr = 'a';写到'a'arr积分的地方.现在这是C标准未定义的行为.当arr设置&c为时,该位置的对象中只有一个字节,并且C标准不保证在对象外部递增该地址后写入其他位置时会发生什么.
  • 正如在这个例子中发生的那样,1004指向arr,所以你写入'a'其中一个字节arr.这可怕地改变了地址arr.
  • 然后arr++;再次递增地址,然后*arr = 'b';写入'b'某处.我们不知道在哪里,因为arr它的价值很低.
  • 然后arr++;再次递增地址,然后*arr = 'c';写入'c'某处.我们不知道在哪里.
  • 然后arr--;arr--;地址返回到它后的值'a'写入.
  • 然后第一个printf调用传递值,arr以使用"%c"说明符打印."%c"用于打印字符,但是arr您传递它是一个指针.但是,您之前'a'写入了指针,因此指针的值'a'在其中一个字节中.
  • 实际上,当"%c"说明符与指针一起使用时,此实现将printf打印指针值中的一个字节,在本例中是您编写的相同字节'a'.所以打印出"a".你不能在其他C实现中依赖这种情况.这是发生在仅仅是因为编译器碰巧把这个情况arr在内存刚过c在内存中,这样的声明*arr = 'a';中写道'a'arr.这不会发生在所有C实现中.你真是幸运."
  • 的写入后'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'.将这些传递给要用"%c"打印的printf打印"b"和"c".

在该程序的第二个版本中,何时arr[0]传递给printf:

  • arr是通过写入'a'其中一个字节而形成的值.这是一些"随机"地址,指向我们没有控制的位置.显然,那里有一个0字符,或者其他一些非打印字符,所以,当arr[0]传递给它时printf,什么都没有打印出来.
  • 传递arr[1]arr[2]打印"B"和"C",因为代码写的'b',并'c'到这些位置.


小智 6

arrarr[0]因为arr[0] 取消引用数组,所以不等价.正确的等价物将是&arr[0].

顺便说一下,你正在做什么调用未定义的行为,因为在递增之后arr,它指向一个无效的内存位置 - 最初它指向一个字符,所以你不能假设它后面有任何东西.


Luc*_*ore 6

这只是未定义的行为 - arr++; *arr = 'a';因为arr指向单一行为是非法的char.任何事情都可能发生.

  • 这也是未定义的行为:`printf("\narr 1 =%c",arr);`因为varargs函数的参数的实际类型(在提升之后)与解码的不同. (2认同)