1. 程式人生 > 其它 >搬運1:關於對C語言中陣列名取地址加減等操作的一點探究

搬運1:關於對C語言中陣列名取地址加減等操作的一點探究

對於陣列名取地址強制轉換的操作

偶然在晚上學了C語言指標後網頁閒逛找題時,被一個數組名取地址搞糊塗了,在自己試驗加探索後我稍微悟了一點東西。
程式碼如下:

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

這裡設定了一個長度為5的陣列,之後定義一個int型別的指標將對a的首地址求地址後加1然後再次強制轉換成int型別的指標傳遞給ptr,我第一反應是a不就是代表指向首個元素的地址嗎,為什麼還要對它求地址

另外求完地址之後+1操作再次把一個指向地址轉換成指標型別給了ptr,這讓我十分費解,我們先來看輸出結果
輸出案例1:

之後我首先刪除了(int *)試著檢視結果:

	int* ptr = (&a + 1);

輸出案例2:

發現輸出案例是沒有變化了,所以說明這裡強制轉化實質上是沒有起到任何效果的,但是對於指標的強制型別轉換真的沒有用嗎?

探究強制轉換

無論任何型別的指標都是佔四個位元組的,只不過指向的值的型別不同從而定義為不同的型別,所以這裡的強制型別轉化應該是為了抱著把陣列名這個指標轉化成int型別的指標。所以我又做了如下測試:
把陣列a改成char型別

(忽略那個沒有重新整理的缺少;分號)對於int的初始化使用char

,會產生警告,所以這裡強制轉化我們是可以理解了。

探究對於陣列名取地址

在網上翻閱其他部落格後查閱得知,因為陣列名是一個右值,而求址運算子&是需要有具體的記憶體空間,也就是變數
//另外我們需要明確陣列名和指標有一個區別是:陣列名是符號地址常量,只是代表了陣列中首個元素的地址,而沒有明確的記憶體空間去儲存它(也就是為什麼不把陣列名直接稱為指標),在編譯時求值並存在編譯器的符號表裡面,其值就是個記憶體地址,而指標是指向某一片區域,並且有一個記憶體空間儲存這個指標,因此有了二級指標三級指標的概念,而對於陣列求地址還是它自己。
所以對於陣列名取地址在早期的編譯器當中是非法的,但是現在是未定義的,因此我們改變程式碼後檢視結果:

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

輸出案例3:

這裡去掉&後得到的答案卻變了,這是因為含&時,對於一個t型別的地址a將進行a+長度**運算數*sizeof(t) ,而這裡不含&時,將只是簡單的對於地址進行加減 運算數 操作。

加減過程

如上所說的運算過程,這裡我們只需要注意一個點也就是含&時的運算
這裡我們對程式碼進行修改供參考。
陣列a的長度為5時

陣列a的長度為4時

(可以看到這裡地址的加減是和長度有關的)
至於和運算元和sizeof()的關係各位可以下去試一試。
------男兒何不帶吳鉤,收取關山五十州。
by二十歲的程式設計男神王大爺