深入理解C語言 轉coolshell

2021-06-22 10:40:53 字數 2525 閱讀 4929

首先,我們先來看下面這個經典的**:1

3 5

intintprintf

2

4

6

8

10

12

14

16

f()

voidvoidintmain()

你知道這段**會輸出什麼嗎?a) 乙個隨機值,b) 42。a 和 b都對(在「在函式外訪問區域性變數的乙個比喻」文中的最後給過這個例子),不過,你知道為什麼嗎?

下面,我們再來看乙個示例:

1

3

5

7

b()

intvoidprintfreturnmain()

這段程式會輸出什麼?,你會說是,3,4,7。但是我想告訴你,這也有可能輸出,4,3,7。為什麼呢? 這是因為,在c/c++中,表達的評估次序是沒有標準定義的。編譯器可以正著來,也可以反著來,所以,不同的編譯器會有不同的輸出。你知道這個特性以後,你就知道這樣的程式是沒有可移植性的。

我們再來看看下面的這堆**,他們分別輸出什麼呢?1

intprintf"%d\n"示例二

a=41; a++ &(, a);

1 intprintf"%d\n"示例四

a=41;(a++ < 42)(, a);

1 intprintf"%d\n"2

4

structintcharint(,(x));

structintcharintchar(,(y));

這個**會輸出什麼?

a) 9,10

b)12, 12

c)12, 16

答案是c,我想,你一定知道位元組對齊,是向4的倍數對齊。

另外,再提一下,上述程式的printf中的%d並不好,因為,在64位下,sizeof的size_t是unsigned long,而32位下是 unsigned int,所以,c99引入了乙個專門給size_t用的%zu。這點需要注意。在64位平台下,c/c++ 的編譯需要注意很多事。你可以參看《64位平台c/c++開發注意事項》。

下面,我們再說說編譯器的warning,請看**:1

3 5

main()

考慮下面兩種編譯**的方式 :

前一種是不會編譯出a未初化的警告資訊的,而只有在-o的情況下,才會有未初始化的警告資訊。這點就是為什麼我們在makefile裡的cflags上總是需要-wall和 -o。

最後,我們再來看乙個指標問題,你看下面的**:1

3 5

7 9

#include

intvoidintprintf"%x\n"printf"%x\n"printf"%x\n"printf"%x\n"}

假如我們的a的位址是:0xbfe2e100, 而且是32位機,那麼這個程式會輸出什麼?

看過這麼多,你可能會覺得c語言設計得真扯淡啊。不過我要告訴下面幾點dennis當初設計c語言的初衷:

1)相信程式設計師,不阻止程式設計師做他們想做的事。

2)保持語言的簡潔,以及概念上的簡單。

3)保證效能,就算犧牲移植性。

今天很多語言進化得很高階了,語法也越來越複雜和強大,但是c語言依然光芒四射,dennis離世了,但是c語言的這些設計思路將永遠不朽。

深入理解C語言 深入理解指標

關於指標,其是c語言的重點,c語言學的好壞,其實就是指標學的好壞。其實指標並不複雜,學習指標,要正確的理解指標。指標也是一種變數,占有記憶體空間,用來儲存記憶體位址 指標就是告訴編譯器,開闢4個位元組的儲存空間 32位系統 無論是幾級指標都是一樣的 p操作記憶體 在指標宣告時,號表示所宣告的變數為指...

深入理解C語言 深入理解指標

關於指標,其是c語言的重點,c語言學的好壞,其實就是指標學的好壞。其實指標並不複雜,學習指標,要正確的理解指標。指標也是一種變數,占有記憶體空間,用來儲存記憶體位址 指標就是告訴編譯器,開闢4個位元組的儲存空間 32位系統 無論是幾級指標都是一樣的 p操作記憶體 在指標宣告時,號表示所宣告的變數為指...

c語言 int轉char 深入理解C語言的指標

指標是c語言的乙個核心特色,它以一種統一方式對不同資料結構中的元素產生引用。對於新手來說,指標總是會帶來很多困惑,但其實指標的基本概念非常簡單。下面是一些指標和它們對映到機器 的關鍵原則。指標型別表明指標指向的是哪一類物件。比如 int ip char cpp 變數ip是乙個指向int型別物件的指標...