基於c語言知識點的補遺介紹

來源:互聯網
上載者:User

使用C很長時間,但是很難說對c的各個點都十分的透徹。雖然c不像c++那樣複雜,但是還有很多嘰裡旮旯兒:並不是他們有多難,而是在於他們平時用的不多,或者和人的第一直覺相悖,再或者初學時經驗有限理解不深根本沒有記住。
下面的這些東西可能來自《c專家編程》或者網路。最近發現基礎的經典的書籍常讀常新,原因可能有兩個:
1、隨著自己經驗的增長,你的認識可能會不一樣,思維的方式也會有所變化,而得到的東西自然會是新的東西。
2、早些時候經驗有限,有些點可能根本就沒有完全理解。現在你可以理解的更深刻。
這方面的書籍再比如《代碼大全》,前幾天翻了一下,又有不同的認識。
進入正題:
1、有符號和無符號的比較:
printf("%d\n", sizeof('A')):列印的值是4(或者是int的長度)而不是1。因為c有型別提升,它會首先把'A'提升為int類型,然後在傳給sizeof。運算式中的參數會提升為int或者double,然後在進行運算,之後再進行裁剪,獲得指定類型的值。
if (-1 <= sizeof(int)):sizeof的傳回值是unsigned int,-1會被類型轉換為unsignedint,然後在進行比較。。
這裡涉及到的是型別提升,隱式類型轉換。它會在運算式中發生,也會在函數入參中發生。
2、枚舉在記憶體中的大小:佔四個位元組。
3、局部變數也是位元組對齊的:
E_T g;
E_T f;
E_T e = false;
char c1;
char c2;
int i1;
char c3;
int i2;
printf("%p, %p, %p, %p, %p, %p, %p, %p\n", &g, &f, &e, &c1, &c2, &i1, &c3, &i2);



--表示是補齊的位。
4、宏定義中的#和##:#的功能是將其後面的宏參數進行字串化操作(Stringfication),簡單說就是在對它所引用的宏變數通過替換後在其左右各加上一個雙引號。
而##被稱為串連符(concatenator),用來將兩個Token串連為一個Token。
5、浮點數不可以用等於比較。
6、void foobar2() 表示函數入參個數有多個,不確定。如果表示沒有產生,應該是:void foobar2(void)
7、全域變數會被初始化為0,但是,棧中的局部變數不會被初始化。
8、inline函數和宏:內嵌函式是真正的函數,但是它是在編譯期的最佳化。
9、 int a[5]; printf("%x\n", a); printf("%x\n", a+1); printf("%x\n", &a); printf("%x\n", &a+1);
最後一個,&a+1,&a表示數組,所以,應該是增加數組大小:4*5個位元組。
10、10U表示一個無符號類型的數字10.
11、移位元運算的優先順序比較低,低於四則運算。
12、左移n位,相當於乘與2的n次方。右移相當於處於2的n次方。
13、指標和數組:
1)、void fun(char buf[100])
{
printf("%d, \n", sizeof(buf));
}
列印的值是4,而不是100。
2)、在一個檔案中char p[10] = "";
在另外一個檔案中聲明:extern char *p;
然後,在聲明的檔案中sizeof(p),答案是4。也就是,sizeof計算的是聲明的類型。
3)對於編譯器而言,一個數組就是一個地址,一個指標就是一個地址的地址。
4)所有作為函數參數的數組名編譯器都會轉換為指標,在其他所有的情況下,數組的聲明就是數組,指標的什麼就是指標。
數組和指標相同情況的規則:
1、運算式中的數組名(與聲明不同)被編譯器當作一個指向該數組的第一個元素的指標。
2、下標總是與指標的位移量相同。
3、在函數的聲明中,數組名被編譯器當作指向該數組第一個元素的指標。這個操作時編譯器完成的。原因是出於效率的考慮。因為這樣就是引用傳遞而非值傳遞。值 傳遞需要拷貝。這也可以看的出sizeof是在彙編中操作的。
arry[-1]的行為是未定義的。
總結:
1)a[i]這樣的形式對a進行訪問,總是被編譯器改寫為像*(a+i)的形式。
2)指標始終是指標,你不可以把它改寫成數組,但是可以通過數組的形式訪問。
3)數組作為函數的參數,會被編譯器改寫成指標。
4)指標和數組的什麼必須配對。
14、聲明與定義:聲明可以由多個,定義只有一個。定義是特殊的聲明,它為對象分配了記憶體。而聲明時普通的聲明,描述其他地方建立的對象。
聲明的優先順序規則:
a:從他的名字開始按照優先次序依次讀取:
b:優先順序的高低:
1、聲明中被括弧括起來的那部分。
2、尾碼操作符:
括弧()表示是一個函數;
方括弧[]表示是一個數組;
3、首碼操作符:*表示指向什麼的指標;
4、const緊跟變數則修飾變數不可修改,緊跟類型則指向的東西不可修改。
15、多維陣列:
a[2][3]:a是一個數組,有兩個元素。每個元素又是一個數組,有三個元素。
記憶體布局:a[0][0],a[0][1],a[0][2],a[1][0]...地址一直變大。
多維陣列,數組的數組作為函數的形參,會被轉化為數組指標,數組的指標,也是行指標。本質上也是指標。
16、結構體預設的位元組對齊一般滿足三個準則:
1) 結構體變數的首地址能夠被其最寬基本類型成員的大小所整除;
2) 結構體每個成員相對於結構體首地址的位移量(offset)都是成員自身大小的整數倍,如有需要編譯器會在成員之間加上填充位元組(internal adding);
3) 結構體的總大小為結構體最寬基本類型成員大小的整數倍,如有需要編譯器會在最末一個成員之後加上填充位元組(trailing padding)。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.