標籤:

為什麼C++使用sizeof關鍵字的時候不需要include <cstddef>頭文件就可以使用?

如題,當c++什麼頭文件都沒有包含時,sizeof關鍵字可以使用,返回的size_t類型也可以使用,size_t類型是包含在頭文件 cstddef中的,然而cstddef頭文件中的定義的NULL宏,ptrdiff_t類型卻不能不包含這個頭文件使用。

還有,c++的typeid關鍵字必須要包含typeinfo這個頭文件才能使用,這是為什麼,好迷啊,難道是未定義行為?


因為sizeof是編譯期的行為,編譯的時候就把它變成一個常量了。雖說sizeof的返回類型是std::size_t,但實際上size_t也只是一個原生類型的typedef。所以這裡肯定是直接用的原生類型,編譯器並不會自己生成個size_t來自找麻煩。

而typeid是運行期的行為,沒法在編譯的時候被取代,必須保持它的返回類型。而它返回的是std::type_info,在&里定義的。你不包含就找不到這個定義,就無法使用。


只有當你顯式使用std::size_t時才需要包含頭文件。當不包含頭文件時,編譯器不認識size_t,但它認識sizeof。

至於為什麼typeid需要&是標準明文規定的:[expr.typeid]


因為 std::size_t 和 std::ptrdiff_t 只是整數類型,實際定義一般都是一個 typedef 。

比如說 sizeof 在產生一個 unsigned int 的情況下,在 &(或其他定義了 std::size_t 的頭文件)里只需要寫 typedef unsigned int std::size_t; 就行。

而 std::type_info 是類(class)類型,沒有辦法被基礎類型代替。所以需要一個頭文件對其進行定義,然後在包含了那個頭文件後才能使用 typeid 。


感覺目前為止的回答都有點混亂……

就好像你用auto推導出一個類型,顯然是不需要這個類型名在當前名字空間的

同理你要處理某個類型也不會因此需要某個頭文件


參考cplusplus的答案size_t 的定義不止在一個頭文件里定義。

至於為什麼能在什麼頭文件不用情況下使用是因為可能c++編譯器給他賦予了類似int一樣的地位。

至於sizeof是關鍵字 不用頭文件就能用。

typeid雖然是關鍵字 。但是也c++也規定必須引用typeinfo 編譯器顯然是做了一些黑科技去實現。


1)你既然都說sizeof是關鍵字,那為什麼還會困惑不需要包含頭文件呢?int也是關鍵字,int需要頭文件嗎?事實上sizeof運算符返回的是一條表達式或一個類型名字所佔的位元組數,它所得到的就是一個size_t類型;

2)size_t 是一種機器相關的無符號整型(unsigned integel type),它只是無符號整型的其中一個別名,它包含在多個頭文件中,所以不需要包含cstddef頭文件就能使用,通常情況下和使用int沒多大不同。NULL同理;

詳見:size_t - C++ Reference

3)typeid是運行時類型識別(run-time type identification,RTTI功能的運算符之一。被定義在typeinfo頭文件中,沒為什麼,詳見:《C++Primer 5th》中文版P732;

4)未定義行為(Undefiend Behaviour,UB)是指你寫的某段程序處於編譯器未定義的異常情況下,可能會導致你的編譯器提示「Undefiend Behaviour」錯誤或程序進入到某個不可預測的狀態中,你說的和UB沒關係


sizeof早已不僅僅是編譯期行為了,從C99有VLA開始。

下面的代碼可以正確按預期輸出:

int n;

scanf("%d", n);

int buf[n];

printf("%d
", sizeof(buf));


推薦閱讀:

如何在C++中拋出一個編譯錯誤?
C++的RAND函數生成的值為什麼存在嚴重的不隨機性?
在c語言中,使用函數指針是否可以提高函數的調用速度 ?

TAG:編程 | C | CC |