c語言指標相關面試題
例1
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int *ptr = (int *)(&a + 1);
printf("%d %d\n", *(a + 1), *(ptr - 1));
system("pause");
return 0;
}
程式結果:2 5
分析:陣列名在sizeof內部單獨出現和&(陣列名)這兩種情況下,陣列名錶示整個陣列。
其他情況下,陣列名均表示首元素的地址。
所以這裡的(a+1)的a表示首元素的地址,+1表示下一個元素的地址,解引用表示下一個下一個元素2.
(&a+1)對a取地址,取得是首元素的地址,+1是指向下一個陣列的起始地址。所以ptr-1指向該陣列的在最後一個元素,解引用表示該元素5.
這裡區分一下:
(a+1):即陣列名+1,指向該陣列內下一個元素。
(&a+1):即&(陣列名)+1,指向下一個陣列的起始。
例2:
struct Test
{
int num;
char *p;
short s;
char c[2];
short sd[4];
}*p;
int main()
{
printf("%#x\n", p);
printf("%#x\n", p + 0x1);
printf("%#x\n", (unsigned long)p + 0x1);
printf("%#x", (unsigned int *)p + 0x1);
system("pause");
return 0;
}
先來看結果:
分析:p是一個結構體指標,他的地址我們其實並不關心。這道題考察了對不同型別的+1,到底是加多少。
對p+1:p是一個指標,對指標+1,加其指向型別的大小。該結構體大小由於記憶體對齊我們可以得到是20,所以16進位制運算得如圖結果。
將p強轉為無符號長整形,對p+1,就是+1。
將p強轉為無符號整形指標型別,對p+1就是加其指向型別的大小,即就是4。
例3:
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4 , 5) };
int *p;
p = a[0];
printf("%d", p[0]);
system("pause");
return 0;
}
這道題有一個很容易出錯的陷阱,在定義二維陣列時用了逗號表示式,所以這個二維陣列並不是題目上的資料,而是{1,3,5,0,0,0};
所以p[0]就是該陣列第一個元素1.
例4
int main()
{
int a[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int *ptr1 = (int *)(&a + 1);
int *ptr2 = (int *)(*(a + 1));
printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));
system("pause");
return 0;
}
分析:這道題考察了對二維陣列的理解,我們知道陣列在記憶體中是線性連續存放的,所以二維陣列也是如此。
&a+1:與一維陣列同理,所以此時+1指向了下一個陣列的起始位置,*(ptr1-1)即就是該陣列的最後一個元素10。
(a+1):指向下一個元素,這裡需要我們將二維陣列看作一維陣列(該陣列有兩個元素,每個元素是一個一維陣列),所以a此時表示第一個元素,+1指向下一個元素即就是第二個一維陣列的起始,*(ptr2-1)即就是上一個一維陣列的最後一個元素5;
例5
int main()
{
char *a[] = { "work", "at", "alibaba" };
char **pa = a;
pa++;
printf("%s\n", *pa);
system("pause");
return 0;
}
這道題主要考察了二級指標,首先a中的字串串都在字元常量區儲存,a指向該區域的起始地址。pa++,指向了下一個字串的地址,所以結果是:at。