繁体   English   中英

C中奇怪的输出问题

[英]strange output issue in c

1)  #include <stdio.h>
    int main()
  {
       int a[5] = {1,2,3,4,5};
       int *ptr = (int*)(&a+1);
        printf("%d %d", *(a+1), *(ptr-1));
        return 0;
   }

输出为2 5 &a表示a[0]的地址,因此&a+1应该是a[1]的地址。 因此, ptr应该保留a[1]的地址。 *(a+1)将为2,但*(ptr-1)也将为2。我不知道它如何打印5。

此表达式很重要: &a+1 实际上是(&a)+1等于(&a)[1] ,它将是指向数组末尾一个元素的指针。

如果我们更“图形化地”看待它,它看起来像这样,并添加了相关的指针:

+------+------+------+------+------+
| a[0] | a[1] | a[2] | a[3] | a[4] |
+------+------+------+------+------+
^      ^                           ^
|      |                           |
|      &a[1] (equal to *(a + 1))   |
|                                  |
&a[0] (equal to a)                 |
|                                  |
&a                                 &a+1

首先, &a的类型是int (*)[5] ,因此您对int *的强制转换将破坏严格的别名(这将导致未定义的行为 )。

第二,由于ptr有效指向a[5]因此ptr - 1将指向a[4]

&a 不是的地址a[0]的,但地址a 值可以相同,但类型不同。 对于指针算术,这一点很重要。

在表达式&a + 1 ,首先具有类型为int (*)[5] &a ,即指向大小为5的数组的指针。当向其添加1时,它实际上将sizeof(a)个字节添加到指针值。 所以&a + 1实际上指向数组末尾的一个字节。 然后,您将此表达式从int (*)[5]int *并将其分配给ptr

然后,当您对*(ptr - 1)求值时, -运算符从ptr的字节值中减去1 * sizeof(int) ,因此它现在指向数组的最后一个元素,即5,这就是要打印的内容。

&a将数组的地址作为数组指针 int (*)[5] 它是一种指向整个数组的指针类型,因此,如果对它进行指针算术运算,则+1表示+sizeof(int[5]) ,这不是您想要的。

正确的代码:

int *ptr = a+1;

值得注意的是,强制转换(int*)隐藏了该错误。 不要使用强制转换使您不了解的编译器错误消失!

首先,您说: &a表示a[0]的地址,所以&a+1应该是a [1]的地址? 不,你错了。 &a的装置地址aa[0] &a+1表示它以整个数组的大小递增,而不仅仅是一个元素的大小,而a+1表示a[1]地址。

这里

int a[5] = {1,2,3,4,5};

让我们假设基址的a0x100

    --------------------------------------
    |   1   |   2   |   3  |   4   |   5  |
    --------------------------------------
   0x100   0x104   0x108   0x112  0x116 ..  
   LSB
    |
    a  

当你做的时候

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

ptr点在哪里? 首先执行(&a+1) ,它的增量是整个数组的大小,

(&a+1) == (0x100 + 1*20) /* &a+1 here it increments by array size */
       == 0x120

所以现在ptr指向

    --------------------------------------
    |   1   |   2   |   3  |   4   |   5  |
    --------------------------------------
   0x100   0x104   0x108   0x112  0x116  0x120  
    a                                     |
                                         ptr points here

现在,当您打印像

printf("%d %d", *(a+1), *(ptr-1));

这里

*(a+1) == *(0x100 + 1*4) /* multiplied by 4 bcz of elements is of int type*/
       == *(0x104) /* value at 0x104 location */
       == 2 (it prints 2)

*(ptr-1)  == *(0x120 - 1*4)
          == *(0x116) /* prints value at 0x116 memory location */
          == 5

注意:-这里

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

&a类型为int(*)[5]即指向5个元素的数组的指针,但是您要转换为int*类型,如@someprogrammerdude所指出的那样,它破坏了严格的别名并导致未定义的行为。

正确的是

int *ptr = a+1;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM