C語言中對數組名取地址


在C/C++中,數組名相當於一個指針,指向數組的首地址。這里“相當於”不代表等於,數組名和指針還是有很多區別的,這個在《C陷阱與缺陷》里有詳盡的講述。而這里要說的是對於數組名取地址的這么一個操作。

如果聲明有如下數組:

int arr[5];

那么,&arr這個操作得到了什么值呢?

如果簡單的認為arr就是一個指向數組首地址的指針的話,那么很自然會想到&arr得到的是一個指向存放arr這個指針的指針,也就是一個二級指針,然而事實卻並不是這樣。

觀察以下代碼:

int arr[5];
printf("%p\n%p\n", arr, &arr);

int *pointer = new int[5];
printf("%p\n%p\n", pointer, &pointer);

在我的電腦上運行的結果如下:

0024FC08
0024FC08
0042B158
0024FBFC

我們可以看到,這里pointer這個指針確實如我們所想指向了不同的地址,但是,arr這個數組名的表現卻和指針不同,arr和&arr指向的地址是一樣的。

這里便體現除了數組名和指針的一個不同之處:對數組名進行&操作,並不是取其地址,而是得到了指向整個數組的指針。也就是說,arr與&arr指向的是同一個地址,但是他們的類型不一樣。arr相當於&arr[0],類型是int *,而&arr是指向整個數組的指針,類型是int (*)[5]。

而這樣的區別顯然也會在對指針或者數組名的加減操作中體現出來,看如下代碼:

int arr[5] = { 1, 2, 3, 4, 5 };
printf("%d\n", *arr);
printf("%d\n", *(arr + 1));
printf("%d\n", *((int*)(&arr + 1)));
printf("%d\n", *((int*)(&arr + 1) - 1));

輸出為:

1
2
-858993460
5

前兩個輸出是很好理解的,對指針的加一操作會使指針按照指針的類型移動相應的位置。

第三行輸出中,首先得到了指向整個數組的指針,對其進行加一操作,指針就指向了整個數組后面的地址,也就是5后面的地址,那么此時將其轉化為int*類型再輸出,就得到了該未初始化過的值。

第四行輸出中,過程為,指針指向5后面的地址,轉為int*類型,此時的減一操作使指針移動一個int類型大小的地址空間,那么便指向了5。

這種特性推廣到二維至多維指針的情況下都是類似的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM