簡 述:對c / c++
中的sizeof()
運算子的一些深入思考;
昨晚看到一題,雖然可以輕易得到結果,但是突然深入思考一些,這是為什麼?
#
include
#include
intmain
(int argc,
char
*ar**)
思考:這裡的sizeof("hello")
,sizeof(str1)
,sizeof(str2)
,sizeof(p1)
,sizeof(p2)
列印出來的值是多少?
下面一列表的a
,b
,c
,d
,sizeof(unsigned int)
,sizeof(int)
列印出來的值又是多少?
理解分析:
在win 10 + vs2015
的x86
模式下,執行結果如下:
上一組的結果執行和分析如下:
sizeof("hello")
的值是 6, 等價於"hello\0"
應在記憶體中佔 6 個位元組,且"hello"
是char [6]
型別(由截圖可知),但為什麼不是char *
或const char *
呢?那就不知道了,反正編譯器的規則就是這麼定的;
sizeof(str1)
的值是 6, 等價於sizeof(char [6])
,在記憶體中一共分配 1*6 個位元組;下標裡面的中的 6 是根據賦值語句,編譯器自己推算出來的;
sizeof(str2)
的值是 100, 等價於sizeof(char [100])
,在記憶體中一共分配 1*100 個位元組;
sizeof(p1)
的值是 4,等價於sizeof(char *)
,等價於sizeof(指標)
sizeof(p2)
的值是 4,等價於sizeof(const char *)
,等價於sizeof(指標)
下一組的結果執行和分析如下:
a
的值是 10, 等價於sizeof(char [10])
,在記憶體中一共分配 1*10 個位元組;
b
的值在不同系統,不同編譯器上,結果是不一樣的(eg: mac10.14.6 + qtcretor5.12.8 && win10 + vs2015); 結果不一直的原因是 無法判定"123456789"+1
到底應該是char [10] + int
之後,應該是什麼型別?只能夠根據自己的編譯器實際決定;且還有一中觀點: 此行是在編譯時刻就已經被替換為具體的數值了,然後這一行的**也會被刪除掉,更加不會被執行,所以其 sizeof 的***是不會實現的(如sizeof(++i)
其實只能夠等價於sizeof(物件(變數 i )的型別)
,其執行時刻在計算其值是不存在的)
注意一點即可,有乙個誤區,以前的 類似於int x1 = 3 + 'b'
能夠順利進行隱式轉換,是因為知道最後應該轉換為 等式 的左側 的 int 型別;而我們這裡系統沒有 左值,故無法知道轉換為什麼型別,所以出現如下截圖,此上下文不支援;
c
的值是 9,沒有什麼好講的,該函式的實現,是遇到第乙個'\0'
就停止;
d
的值是 8 ?(兩個不同環境都是 8,有點費解),這個不明所以;檢視原始碼 strlen() 的實現如下size_t strlen(const char *__s);
,按照我的理解,應該是等價於d = strlen((const char *)("123456789"+1))
的,顯示結果依舊為 8;這個結果為啥是 8, 有點費解,不過覺得沒有**的必要,也不是本文談論的重點;此行多**無意義,且這樣寫,有點 「無中生有」,「惹是生非」,「搞事情」 的感覺
sizeof(unsigned int)
的值是 4,不用解釋
sizeof(int)
的值是 4,不用解釋
下面是另外角度來思考此問題:
[角度 1]:
sizeof()
是 返回乙個型別的在記憶體中說佔的位元組數。 是屬於運算子, 同為 運算子 的還有+
、-
、*
、/
、%
等。而這個是在編譯時候就被執行,而非執行時候執行,一開始就已經是計算機被知道的。
c 標準和實際上的 編譯器 一開始就定義好了,在 32 位電腦中,int
佔據 4 位元組,char
佔據 1 位元組;
對於內建的基本資料型別來說,下面是很容易理解,覺得一開始就被編譯機在記憶體裡面分配了這麼多的變數:
sizeof
(int)--
> 顯示 4 位元組
sizeof
(char)--
> 顯示 1 位元組
而 對於復合資料型別來求位元組大小,其是需要根據 組合的基本資料型別 來給出實際的記憶體中所佔的位元組大小,比如自定義 類:
sizeof
(自定類)
--> 顯示 位元組對齊後的 位元組
sizeof
(陣列)
--> 顯示 符合型別的陣列 位元組
sizeof
(int[4
])--> 顯示 4
*4 位元組 // 這樣就容易理解了
[角度 2]:
[p101] 類似於都是指代 《c++ primer 中文版 第5 版》一書的頁碼忽然發覺有點不簡單,
str1
是陣列型別,屬於復合型別[p101],表示式右側"hello"
是什麼型別(是char
、char *
還是const char *
呢?),其實也並不重要(雖然知道了是char [6]
型別 );但是它一定是給 陣列str1
賦值的;且定義的賦值寫法如此
[角度 3]:
有人自己使用如下兩個巨集,來實現了該sizeof()
的實現;注意的是,這是網友自己使用巨集來實現的,而非 編譯器 就是這樣實現的,但是對於我的理解有所幫助;
//適用於非陣列
#define
_sizeof
(t)(
(size_t)
((t*)0
+1))
//適用於陣列
#define
array_sizeof
(t)(
(size_t)
(&t+1)
-(size_t)
(&t)
)
[角度 4]:
sizeof
運算子,實際上有兩種使用方式,且書上明確有說sizeof
實際上並不會去計算其運算子物件的值 [p139],sizeof
運算時候,也不會將數組成指標來處理;
sizeof
(type)
// 返回 型別 在記憶體中所佔的位元組大小
sizeof expression // 返回 表示式結果的 型別 在記憶體中所佔的位元組大小
c 中的sizeof 運算子
sizeof是乙個操作符 operator 其作用是返回乙個物件或型別所佔的記憶體位元組數。sizeof有三種語法形式 1 sizeof object sizeof 物件 2 sizeof object sizeof 物件 3 sizeof type name sizeof 型別 物件可以是各種型別...
C語言 sizeof 運算子
今天看了一篇文章叫 c c 刁鑽問題各個擊破之細說sizeof 然後自己想寫一寫。sizeof的作用 1.求基本型別和復合型別所佔的記憶體位元組數 如 sizeof int sizeof int 2.求某個變數或者常量所佔的記憶體位元組數 如 int i sizeof i sizeof 5 size...
c語言中的sizeof運算子
sizeof運算子在編譯期間執行 除非運算元是乙個可變長度陣列 所以不會導致執行時開銷 sizeof運算元是乙個陣列名時返回的是該陣列所佔位元組總個數,而非陣列元素。sizeof運算子求陣列長度 int a 5 sizeof a sizeof a 0 sizeof運算子的運算元只有是乙個真實的陣列名...