如何理解c/c++語言的聲明以及類型?
完全不懂,感覺這個比指針複雜至少20倍。
http://1.int a 表示a是一個int類型↑↑↑↑↑題主就懂上面一個 ↑↑按照我所觀察到的編譯器的邏輯:int* a則表示a是(int*)類型?int** a則表示a是(int**)類型,那麼問題來了,*到底是什麼玩意。
還有c++當中的引用:intb=a。明明表示的是a是b的別名,其實告訴我們的道理就是,a其實就是b所以我畫了一張圖:所以此時a就是b,所以b的類型是int,而不是int。還有int *p[5]是什麼東西p的類型又是什麼還有int (*p[5])()是什麼.....最後,c專家編程第三章我一個字都看不懂。
因為我連int*是什麼都不知道
首先說一下C語言變數聲明的邏輯
C語言用的是解方程式的聲明法,什麼是解方程int*a;表示有這麼一個變數a,*a運算(解引用a)的類型是int,所以a是指向int的指針同理int arr[10]表示有這麼一個變數arr,arr[i]運算(帶偏移量的解引用)得到的類型是int,所以arr是10元素的int數組函數也一樣int func(int, int),有這麼一個東西,用兩個int調用它(括弧也是運算符知道吧),得到一個int,所以func是個接受兩個int,返回一個int的函數所以有人習慣尊重C的解方程式的聲明,把*挨著變數名寫,這樣聲明和使用的寫法一致,但是我不喜歡
然後說你題目里那個複雜聲明int(*p[5])()
看外層,int(xxxx)(),說明內層東西的類型是個函數,接受空,返回int看內層,*p[5],解方程:對p進行[]運算,再進行*運算,得到了外層一個接受空返回int的函數所以p是什麼,p是一個數組,5個元素,每個元素是一個指針,指針指向函數,函數接受空返回intGitHub - MichaelSuen-thePointer/mqcdecl: A "clean room" and "naive" implementation of cdecl.org今天上午剛寫了一個C語言複雜聲明翻譯器,你這裡就用上了。這種複雜聲明實際工程里不能寫,但是你不能不清楚他的原理,他們本質都是解方程============更新一下覺得這裡說的不是很明確,於是我寫了一篇博客,地址在這裡淺談C語言變數聲明的解析============更新結束然後指針是什麼
對於x86的棧內存模型,局部變數儲存在棧中,棧是操作系統給程序開闢的一塊線性的內存空間,變數在其中線性排布,既然是內存空間,那就會有對應的地址用來向操作系統/計算機底層硬體存取這塊內存空間,指針就是一個用來裝內存地址的變數。你聲明了一個變數int a;對應的彙編代碼就會在棧上給你分配一個4byte的空間(具體怎麼分配的參見x86彙編以及cdecl調用約定),當你修改這個int的時候,儘管你沒有在C語言里直接使用指針,對應的彙編代碼依然是用那個int的內存地址來修改它的。當你取地址的時候,對應彙編代碼就會拿到這4byte空間的第一個位元組對應的內存地址。你聲明了一個指針變數int*p;,同樣作為一個變數,內存中也會有一塊對應的空間給這個變數,當你把取到的a的地址賦給p的時候,前面拿到的那個地址作為一個值,就存到了p這個變數所佔據的4個byte空間里。這就是指針。至於C++的int,內部實現也是多半用的指針,不過引用相比表意更不明確的指針,很多情況下是可以優化的,有時也不一定用指針。很簡單,從被聲明的標識符開始,先右後左,遇括弧返回。
int A;
很簡單,A是一個intint *A;
從A開始:A是一個變數,*表示它是一個指針變數,int表示這個指針變數指向intint **A;
A是一個變數,*表示它是一個指針變數,第二個*表示前一個指針變數指向的類型還是一個指針,int表示A這個指針變數指向的指針變數指向一個int
int A[5];
A是一個變數,(向右)這個變數是一個有5個元素的數組,(向左)這個數組存儲intint *A[5];
A是一個變數,(向右)這個變數是一個有5個元素的數組,(向左)這個數組存儲指針,指針指向的類型是intint **A[5];
A是一個變數,(向右)這個變數是一個有5個元素的數組,(向左)這個數組存儲指針,指針指向的類型還是一個指針,最終指向的數據類型是int當然還有很多更為複雜、連老鳥都能搞暈的寫法。那些就屬於魔道了。
真需要作複雜的聲明時,建議用typedef一層層定義別名、最後用typedef的別名完成聲明。這樣寫出的聲明易懂、無歧義、便於閱讀。C語言複雜聲明解析
《深入理解計算機系統》,回答你所有問題。但是考慮到這本書可能對初學者不太友好,簡單說一下:
首先內存的作用和紙差不多。
int a = 1; /* 在紙的第一行位置寫一個1(請嘗試用筆寫下來)。 */
int * b = a; /* 在紙第二行位置寫下:「第一頁第一行有一個int」(在內存中保存的東西一般是0x0101這樣的東西) */
*b = 2 /* 把第二行指示的位置的數據修改為2 */
b = 0x0202 /* 第二行修改為:「第二頁第二行有一個int」(實際上可能並沒有)*/
其他問題,恕答主很懶,答主覺得解釋清楚指針是什麼,其他問題也就很好理解了。提示一下,代碼和數據一樣要被載入到內存中的,也是有地址的。
PS:多看書。沒錯int*就是一個類型,至於為什麼要有int*這樣的類型原因很簡單,這門語言就是需要這麼一種類型才能完成一些事情,而int做不到。
int*和int的區別在於,int就是一個int,只要關心它的值就可以了,而int*除了本身值有意義之外,還可以進行一次解引用int a = 1;int *pa = a;
這個例子中,a的值是1這是我們關心的,而a的地址(假設是0x12345678)是我們不需要關心的。pa的地址(假設是0x87654321)我們不需要關心,而它的值是0x12345678就是有意義的,另外pa還可以解引用一次,*pa的結果是1所以int*是一個類型,並且這個類型是C語言必須要的多維指針理解也簡單,每加一個*,就可以多解引用一次同理int是C++語言必須要的一種類型,理由類似
所以題主第二個問題中的說法是不對的,b是int類型,而不是int類型。如果b是int,那它就做不到引用的功能了。int *p[5]
就是指針的數組,這個數組中有5個int*,分別用p[0],p[1],p[2],p[3],p[4]訪問int (*p[5])()這是函數指針數組,請看栗子
int fun1()
{
return 1;
}
int fun2()
{
return 2;
}
int fun3()
{
return 3;
}
int fun4()
{
return 4;
}
int fun5()
{
return 5;
}
int _tmain(int argc, _TCHAR* argv[])
{
int(*p[5])();
p[0] = fun1;
p[1] = fun2;
p[2] = fun4;
p[3] = fun4;
p[4] = fun5;
printf("%d
", p[0]());
printf("%d
", p[1]());
printf("%d
", p[2]());
printf("%d
", p[3]());
printf("%d
", p[4]());
getchar();
return 0;
}
研究一下c++操作符的作用,優先順序,以及結合性表格就能搞清楚。
簡單來說,只需要記住以下四點。
1)指針"T *a",數組"T a[...]",函數"T a(...)",T可嵌套,a可省略(作為類型)
2)A*B[...] 等於 A*(B[...]) ,A *B(...) 等於 A *(B(...)),必要時加括弧3)假如op1,op2各自代表*,,或,那麼 ... op1 B op2 ... 等於 ... op1 (B op2 ...)4)如果和連續出現,只有... ... 等於 ... ...,其餘情況為... ...PS:「c專家編程第三章我一個字都看不懂」,一看就沒好好讀過KR,基礎太爛。有時候編譯器就是那麼怪,C++編譯器更怪。你結合內存圖消化了就好,不要糾結語法細節,畢竟你不是做編譯器的。
呵呵,比指針複雜20倍啊...int a中間加一個*,指針中間加兩個*,指針的指針中間加三個*,指針的指針的指針如果不談指針,你可以想成爸爸int a的爸爸,的爸爸的爸爸的爸爸的爸爸的爸爸如果還不行,我們上一首後現代兒歌(來自 小蓓蕾組合)/**********************************************/
- (白)爸爸好,媽媽好,爺爺好,奶奶好
- 爸爸的爸爸叫什麼
- 爸爸的爸爸叫爺爺
- 爸爸的媽媽叫什麼
- 爸爸的媽媽叫奶奶
- 媽媽的爸爸叫什麼
- 媽媽的爸爸叫外公
- 媽媽的媽媽叫什麼
- 媽媽的媽媽叫外婆
- 相逢開口笑,嘴巴甜又巧
- 叫得全家老少樂呀樂陶陶
- 見誰都要叫,千萬別叫錯
- 懂禮貌的孩子就是我就呀就是我
- 爸爸的兄弟叫什麼
- 爸爸的兄弟叫伯伯和叔叔
- 爸爸的姐妹叫什麼
- 爸爸的姐妹叫姑姑
- 媽媽的兄弟叫什麼
- 媽媽的兄弟叫舅舅
- 媽媽的姐妹叫什麼
- 媽媽的姐妹叫阿姨
- 相逢開口笑,嘴巴甜又巧
- 叫得全家老少樂呀樂陶陶
- 見誰都要叫,千萬別叫錯
- 懂禮貌的孩子就是我,就呀就是我
- (白)外公好,外婆好,叔叔好,伯伯好
- 爸爸的爸爸叫什麼
- 爸爸的爸爸叫爺爺
- 爸爸的媽媽叫什麼
- 爸爸的媽媽叫奶奶
- 媽媽的爸爸叫什麼
- 媽媽的爸爸叫外公
- 媽媽的媽媽叫什麼
- 媽媽的媽媽叫外婆
- 相逢開口笑,嘴巴甜又巧
- 叫得全家老少樂呀樂陶陶
- 見誰都要叫,千萬別叫錯
- 懂禮貌的孩子就是我,就呀就是我
- /**********************************************/
- 標準有向無環圖,二叉樹不行
- 好男人就是我,我就是int a
為實物 取外號
這可是門技術活, 要考慮怎麼把外號取得好聽(是否好記憶-&>好區分)!
取得響亮(能傳播多遠)!
還要讓人能快速通過外號找到實物(別太作,取超多的外號,還外號的外號...把人繞暈了)!推薦閱讀: