C語言深度剖析筆記2

2021-09-02 18:50:17 字數 2257 閱讀 2853

int a[5];

a作為右值時,代表陣列首元素的位址,而非陣列的首位址。

sizeof(a)的值為sizeof(int)*5 為20

sizeof(a[0]) 的值為sizeof(int) 為4

sizeof(a[5]) 為4 為什麼不報錯呢?因為函式求值是在執行的時候,而關鍵字sizeof求值是在編譯的時候.雖然並不存在a[5]這個元素,但是這裡也並沒有真正訪問a[5],而是僅僅根據陣列元素的型別來確定其值.因此這裡使用a[5]並不會出錯。

sizeof(&a[0])的值在32位系統下為4,這很好理解,取元素a[0]的首位址

sizeof(&a)也為4,取陣列a的首位址。

陣列名a作為左值和右值的區別:

簡單而言,出現在賦值符"=「右邊的就是右值,出現在賦值符」="左邊的就是左值。比如,x = y。

左值:編譯器認為x的含義是x所代表的位址。這個位址只有編譯器知道,在編譯的時候確定,編譯器在乙個特定的區域儲存這個位址,我們完全不必考慮這個位址儲存在**。

右值:編譯器認為y的含義是y所代表的位址裡面的內容,這個內容是什麼只有到執行時才知道。

當a作為右值時其意義與&a[0]是一樣的,代表的是陣列首元素的位址,而不是陣列的首位址(sizeof(a)中,a表示的是陣列名,此時a並沒有被用作右值),這是兩碼事。但是注意,這僅僅是代表,並沒有乙個地方來儲存這個位址,也就是說編譯器並沒有為陣列a分配一塊記憶體來儲存其位址,這一點就與指標有很大區別.

a作為右值,我們清楚了其含義,那麼作為左值呢?

a不能作為左值!編譯器會認為陣列名作為左值代表的意思是a的首元素的首位址,但是這個位址一開始的一塊記憶體是乙個總體,我們只能訪問陣列的某個元素,而無法把a當左值。其實我們完全可以把a當做乙個普通的變數來看,只不過這個變數內部分為很多小塊,只能通過分別訪問這些小塊來達到訪問整個變數a的目的。

(a) char p = 「abcdef」;

(b)char a = 「123456」;

一.以指標的形式訪問指標和以下標的形式訪問指標

a定義了乙個指標變數p,p本身在棧上佔4位元組,p裡儲存的是一塊記憶體的首位址。這塊內存在靜態區,其空間大小為7位元組,這塊記憶體也沒有名字,對這塊記憶體的訪問完全是匿名的訪問。如果現在需要讀取字元』e』,我們有兩種方式:

1.以指標的形式:(p+4).先取出p裡面儲存的位址值,假設為0x0000ff00;再加上4個字元的偏移量,得到新的位址0x0000ff04;然後取出0x0000ff04位址上的值。

2.以下標的形式:p[4]。

二、以指標的形式訪問陣列和以下標的形式訪問陣列

例子b定義了乙個陣列a,a擁有7個char型別的元素,其空間大小為7.陣列a本身在棧上面.對a元素的訪問必須先根據陣列的名字a找到陣列首元素的首位址,然後根據偏移量找到相應的值.這是一種典型的"具名+匿名"訪問.如果現在需要讀取字元』5』,我們有兩種方式;

1.以指標的形式:*(a+4)。a這時候代表的是陣列首元素的首位址,假設為0x0000ff00;再加上4個字元的偏移量,得到新的位址0x0000ff04;然後取出0x0000ff04位址上的值。

2.以下標的形式a[4]

a和&a的區別

例子:

#include int main()

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

printf("%d,%d",*(a+1),*(ptr-1));

return 0;

}

對指標進行加1操作,得到的是下乙個元素的首位址,而不是原有位址值直接加1.所以,乙個型別為t的指標的移動,以sizeof(t)為移動單位.因此,對上題來說,a是乙個一維陣列,陣列中有5個元素;ptr是乙個int型的指標。

&a+1:取陣列a的首位址,該位址的值上加上sizeof(a)的值,即:&a+5*sizeof(int),也就是下乙個陣列的首位址,顯然當前指標已經越過了陣列的界限。

(int )(&a+1):則是把上一步計算出來的位址,強制轉換為int型別,賦值給ptr。

*(a+1):a和&a的值是一樣的,但意思不一樣,a是陣列首元素的首位址,也就是a[0]的首位址,&a是陣列的首位址。a+1是陣列下一元素的首位址。即a[1]的首位址,&a+1是下乙個陣列的首位址,所以輸出2.

*(ptr-1)指向a[4] = 5;

指標和陣列的區別

《C語言深度剖析》筆記

c語言深度剖析 筆記 1.在c語言中,凡不加返回值型別限定的函式,就會被編譯器作為返 回整形處理。2.register 變數必須是乙個單個的值,並且其長度應小於或等於整型 的長度。而且 register 變數可能不存放在記憶體中,所以不能用取 址運算子 來獲取 register變數的位址。3.int...

C語言深度剖析筆記

1.變數定義 所謂的定義就是 編譯器 建立乙個物件,為這個物件分配一塊記憶體並給它取上乙個名字,這個名字就是我們經常所說的變數名或物件名。2.變數宣告 1.告訴編譯器,這個名字已經匹配到一塊記憶體上了,下面的 用到變數或物件是在別的地方定義的。宣告可以出現多次。2.告訴編譯器,這個名字已被預訂了,別...

C語言深度剖析筆記(二)

系統大小端模式檢測 include int checksystem t t.a 0x12345678 return t.c 0x78 int main define是編譯預處理指令,在編譯預處理時換,不作正確性檢查,不論是否正確只進行帶入替換,只有在編譯已被展開的源程式時才會發現可能的錯誤並報錯。2...