c – 数组a和&a的起始地址

在以下两行中,

char a[5]={1,2,3,4,5};
char *ptr=(char *)(&a+1);
printf("%d",*(ptr-1));

这在屏幕上打印5个.当使用a代替& a时,

char a[5]={1,2,3,4,5};
char *ptr=(char *)(a+1);
printf("%d",*(ptr-1));

这打印1

a和& a都是数组的起始地址.所以为什么这有区别?

char * ptr =& a 1;

显示警告.

既然你看起来很陌生,那么让我用简单的语言向你解释,而不是去做严谨的解释.

你看,对于你上面的进程,a和& a将具有相同的数值,我相信这就是你的整个混乱所在.你可能想知道如果它们是相同的,下面的内容应该在a之后给出下一个地址两种情况,通过指针算术:

(&a+1) and (a+1)

但事实并非如此!!数组的基地址(这里是一个)和数组的地址不一样! a和& a可能在数字上相同,但它们不是同一类型. a是char *类型,而& a是char(*)[5]类型,即& a是指向(地址)和大小为5的数组的指针.但是你知道的是a的地址数组的第一个元素.在数字上,它们与使用^下面的插图中看到的相同.

但是当你递增这两个指针/地址时,即(a 1)和(& a 1),算术完全不同.而在第一种情况下它会“跳转”到数组中下一个元素的地址,在后一种情况下,它会跳过5个元素,就像5个元素的数组大小一样!.现在呢?

1 2 3 4 5  
  ^               // ^ stands at &a

  1 2 3 4 5
           ^     // ^ stands at (&a+1)

  1 2 3 4 5
  ^              //^ stands at a

  1 2 3 4 5
    ^            // ^ stands at (a+1)

以下将给出关于未指定数组绑定的错误,因为未明确指定大小如下所示意味着当遇到类似(& a 1)之类的进程时,进程将不知道要“跳转”到多少元素.

char a[]={1,2,3,4,5};
char *ptr=(char *)(&a+1);  //(&a+1) gives error as array size not specified.

现在到你将指针/地​​址递减为(ptr-1)的部分.在第一种情况下,在你来到减量部分之前,你应该知道在它上面的语句中发生了什么,它被转换为类型char *:

char *ptr=(char *)(&a+1);

这里发生的是你“剥离”类型为char(*)[5]的原始类型(& a 1),然后将其转换为类型char *,它与a的类型相同,即数组的基地址.(再次注意数组的基地址和数组的地址之间的区别.在上面的语句中进行强制转换和赋值之后,接着是printf()中的递减,ptr现在给出了内存位置的正确性在数组的最后一个元素之后,即5.

1 2 3 4 5
          ^     // ^ stands at location of 5, so *ptr gives 5

因此,当您将指针ptr递减为*(ptr-1)后取消引用时,它会按预期打印值5.

最后,将其与第二种情况进行对比,其中印有1.看看我使用符号^给出的插图.当你将a增加为1时,它指向数组的第二个元素,即2,并且你将此地址分配给ptr.So当你将ptr减为(ptr-1)时,它会跳回一个元素,现在指向数组的第一个元素,即1.在第二种情况下解除引用ptr给出1.

1 2 3 4 5
  ^            // ^ stands at address of 1, so *ptr gives 1

希望这一切都清楚.

翻译自:https://stackoverflow.com/questions/16312299/starting-address-of-array-a-and-a