在c c 語言中,為什麼c 5 5 c

2021-07-04 23:39:57 字數 2035 閱讀 4582

這個問題,當初是在德問上看見的,起初自己也不知道其機理,猜測與c語言的編譯機制有關,於是通過反彙編、猜測、驗證,最終找到了原由。

下面是我分析該問題的過程,首先來看一段關於陣列的**:

#include

using

namespace

std;

int main()

a[3] = 11;

3[a] = 15;

cout

<< a[3] << endl;

system("pause");

return

0;}

使用microsoft visual 2010對**進行反彙編:

7:
根據上面的彙編**,我們可以發現編譯器對於a[i]的彙編表示:

a[i]:  dword ptr [ebp+ecx*4-1ch]
其中dword,表示雙字(四個位元組);ptr,pointer縮寫,表示指標;[addr]中的addr表示位址位置。整個式子表示從位於ebp+ecx*4-1ch的位址處,提取變數大小為4個位元組的變數值,與a[i]進行對比,可以猜測:

a[i]        [ebp+ecx*4-1ch]

a ebp - 1ch //陣列首位址

i ecx //陣列下標

int 4 //變數大小

通過microsoft visual 2010對比aebp-1ch的值,可以發現它們相等,也就證明了我們上面的對應關係,總結出編譯器對於陣列的解釋:

ptr [陣列首位址 + 陣列下標 * sizeof(變數型別)]
貌似這個結論,比較顯然,但是如果按照這個結論來看:

接下來我們做以下實驗進行驗證:

int a[5];

int *p = a;

int i = 2 , b = &a;

//a: 陣列首位址

i[a] = 1; // 正確

2[a] = 1; // 正確

(i+2)[a+1]=1; // 正確

//p: int指標變數

i[p] = 1; // 正確

2[p] = 1; // 正確

(i+2)[p+1]=1; // 正確

//無指標變數

b[2] = 3; // 失敗 error c2109: 下標要求陣列或指標型別

2[b] = 4; // 失敗 error c2109: 下標要求陣列或指標型別

i[b] = 5; // 失敗 error c2109: 下標要求陣列或指標型別

b[i] = 6; // 失敗 error c2109: 下標要求陣列或指標型別

因此編譯器對於陣列的處理時,必須要有乙個指標變數作為基址,其它數值作為陣列下標。你可能不禁會問:如果存在兩個指標變數,怎麼辦? 按照上面的推測,存在兩個指標變數,編譯器貌似是無法處理的,實驗驗證也表明,存在多個指標變數,將會報錯:

int a[5],b[5];

a[b+2] = 4; // 失敗 error c2107: 非法索引,不允許間接定址

至此問題分析完畢,總結如下:

a[i] 與 i[a]的含義一樣

表示式中必須出現乙個指標變數,無論其位置如何,其被視為陣列首位址,剩餘的值作為陣列下標

在C語言中 巨集定義是什麼?

巨集定義是c提供的三種預處理功能的其中一種,這三種預處理包括 巨集定義 檔案包含 條件編譯 巨集定義又稱為巨集代換 巨集替換,簡稱 巨集 格式 define 識別符號 字串 其中的識別符號就是所謂的符號常量,也稱為 巨集名 預處理 預編譯 工作也叫做巨集展開 將巨集名替換為字串。掌握 巨集 概念的關...

在c語言中是什麼意思?

是乙個整體,它是用於指向結構體子資料的指標,用來取子資料。換種說法,如果我們在c語言中定義了乙個結構體,然後申明乙個指標指向這個結構體,那麼我們要用指標取出結構體中的資料,就要用到 舉個栗子 問題中的p p a,意思是將p指向的乙個結構體例項中的自資料a賦值給p.首先定義乙個結構體 struct f...

C語言中為什麼要清除 bss段

bss段裡的內容 顯示初始化為0或者未顯示初始化的全域性變數 顯示初始化為0或者未顯示初始化的static區域性變數。為什麼要清除.bss段 c語言程式在編譯完成後,初始化為非零的全域性變數存放在.data段,而未初始化或初始化為0的全域性變數存放在.bss段中。在生成的可執行檔案中,只有.data...