代碼如下:
#includeint main(void) { int a[5] = {1, 2, 3, 4, 5}; int *ptr = (int *)(&a+1); int *p1 = a; int *p2 = &a[0]; int *p3 = (int *)(&a); if(p1 == p2){ printf("p1 == p2\n"); }else{ printf("p1 != p2\n"); } if(p1 == p3){ printf("p1 == p3\n"); }else{ printf("p1 != p3\n"); } if(p2 == p3){ printf("p2 == p3\n"); }else{ printf("p2 != p3\n"); } printf("%d %d\n",*(a+1),*(ptr-1)); int *p4 = ++p1; int *p5 = ++p3; if(p4 == p5){ printf("p4 == p5\n"); }else{ printf("p4 != p5\n"); } return 0; }
裡面所有的判斷都是相等,打印的兩個值是2和5.
原因如下:
&a是數組的首地址,它的類型是int(*)[5],因此+1是加的是數組個數的步長。指針加1要根據指針自身類型加上一定的值, 不同類型的指針+1之後增加的大小不同。因此&a + 1後指向的地址對數組來說是越界的,注意前面有個int(*)又強制將他轉為int*了。因此計算*(ptr - 1)的時候,ptr是個int類型的指針,減一等於往左移動sizeof(int*)個字節,因此又指向a[4]了,他的值等於&a[4].
為此雜家又對p4和p5作了驗證,為啥結果p4會等於p5呢?原因就在於申請p3的時候對&a進行了強制類型轉換,
int *p3 = (int *)(&a);
如果不加這個轉換,是編譯不過去的。加了轉換之後p3等於p1也等於p2,他的類型跟另外兩個一樣都是int*類型的了,因此移動相同位後地址也是一樣的。很多人糾結就糾結在&a、a、&a[0],根本原因在於對&a進行了強制類型(int*)轉換。