1

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

#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]正在打印分配什么?

4

3 回答 3

9

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

  • 编译器将c某个地址放在堆栈上,比如 1003(单个字节)。
  • 编译器将arr某个地址放在堆栈上,例如 1004-1007(四个字节)。
  • 该语句arr = &c;c1003 的地址放入arr.
  • 该语句arr++;将 1 添加到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 实现中发生的这种情况。在这种情况下发生这种情况只是因为编译器恰好在arrin memory 之后将其放入cmemory,因此语句*arr = 'a';写入. 这不会在所有 C 实现中发生。你得到了“幸运”。</li> 'a'arr
  • 写入'a'into之后arrarr是指向某个地方,虽然我们不知道在哪里。我们称这个位置x
  • 声明arr++;*arr = 'b';写信'b'到该地点x+1
  • 声明arr++;*arr = 'c';写信'c'到该地点x+2
  • 然后两条arr--;语句返回arr指向xarr[1]处的字符也是如此x+1,即是'b'arr[2]'c'。将这些传递给 printf 以使用“%c”打印“b”和“c”。

在程序的第二个版本中,whenarr[0]被传递给printf

  • 的值arr是通过写入'a'其字节之一形成的值。这是一些“随机”地址,指向我们无法控制的任何位置。显然那里有一个 0 字符,或者其他一些非打印字符,所以,当arr[0]传递给时printf,什么都不会打印。
  • 传递arr[1]arr[2]打印“b”和“c”,因为代码写入'b''c'这些位置。
于 2012-12-18T17:59:08.370 回答
6

arr不等同于arr[0],因为arr[0] 取消引用数组。正确的等价物是&arr[0].

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

于 2012-12-18T16:40:39.300 回答
6

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

于 2012-12-18T16:41:23.367 回答