簡體   English   中英

sizeof如何知道操作數數組的大小?

[英]How does sizeof know the size of the operand array?

這可能是一個愚蠢的問題,但是當你沒有傳入數組中的元素數量時,sizeof運算符如何知道數組操作數的大小。 我知道它不會返回數組中的總元素,而是以字節為單位返回大小,但為了得到它,它仍然必須知道數組何時結束。 只是好奇這是如何工作的。

sizeof在編譯時解釋,編譯器知道數組是如何聲明的(因此它占用了多少空間)。 在動態分配的數組上調用sizeof可能無法執行您想要的操作,因為(如您所述)未指定數組的結束點。

你理解這個問題的根本問題可能是因為你混淆了數組和指針,正如許多人所做的那樣。 但是, 數組不是指針 double da[10]是十個double的數組,而不是double* ,當你要求它評估sizeof(da)時,編譯器當然知道它。 你不會對編譯器知道sizeof(double)感到驚訝嗎?

數組的問題在於它們在許多上下文中自動衰減指向它們的第一個元素(比如它們傳遞給函數時)。 但仍然,數組是數組,指針是指針。

除了一個案例, sizeof在編譯時就是這樣。 在編譯時,編譯器會跟蹤對象的完整類型[編輯:嗯,它知道關於對象類型的所有內容 - 無論如何 - 如果類型不完整,那么不包括大小,嘗試使用sizeof將失敗], sizeof基本上只是將一條信息從編譯器“導出”到正在編譯的代碼中,因此它在結果代碼中基本上是一個常量。

例外情況是將sizeof應用於可變長度數組(VLA) 1 當應用於VLA時, sizeof評估其操作數(否則不會),並生成VLA的實際大小。 在這種情況下,結果不是常數。


1.在V99中,VLA正式成為C的一部分,但在此之前,一些編譯器支持它們。 雖然不是C ++的正式部分,但是一些編譯器(例如,g ++)也包括VLA作為C ++的擴展。

編譯器知道應用程序中每種類型的大小,而sizeof只是請求編譯器為您生成該值。

Sizeof是一個編譯Sizeof算符; 它擁有與編譯器一樣多的信息。 (顯然編譯器確實知道數組的大小)。

這就是為什么如果在指針上調用sizeof ,則獲得指針的寬度,而不是指針所指向的數組的大小。

Sizeof只能應用於完全定義的類型。 編譯器要么能夠在編譯時確定大小(例如,如果你有一個類似int foo [8]的聲明;),或者它將能夠確定它必須添加代碼來跟蹤變量的大小-length數組(例如,如果你有一個類似int foo [n + 3]的聲明;)。

相反,這里其他的答案,請注意,作為C99的,sizeof()會不一定在編譯時決定,因為陣列可以是可變長度。

如果您在局部變量上使用sizeof ,它會知道您聲明了多少個元素。 如果你在函數參數上使用sizeof ,它就不知道; 它將參數視為指向數組的指針, sizeof指定指針的大小。

來自wiki的引用:

編譯器作者有責任以特定的方式實現sizeof運算符,並且對於給定的語言實現是正確的。 sizeof運算符必須考慮底層內存分配方案的實現,以獲取各種數據類型的大小。 sizeof通常是編譯時運算符,這意味着在編譯期間,sizeof及其操作數將被結果值替換。 這在C或C ++編譯器生成的匯編語言代碼中很明顯。 出於這個原因,sizeof有資格作為運算符,即使它的使用有時看起來像函數調用。

sizeof運算符 '知道'所有原子數據類型的大小,因為結構,聯合和數組只能通過組裝原子類型來構造,因此很容易確定任何類型的數組的大小。 它使用基本算法來確定復雜類型(在編譯期間)。

sizeof 通常在編譯時進行評估。 值得注意的例外是C99的可變長度數組。

int main(int argc, char **argv)
{
    if (argc > 1)
    {
        int count = atoi(argv[1]);
        int someArray[count];

        printf("The size is %zu bytes\n", sizeof someArray);
    }
    else puts("No");
}

sizeof在編譯時計算。 這就是為什么在創建動態數組時,可以通過以下方式創建它。

char * array;
int size;
//Get size somehow.
array = malloc(size*(sizeof(char)));

//現在在編譯期間,編譯器肯定知道char的大小。 因為它必須將它們對准內存。 此時,OS知道它必須分配多少大小。

另一方面, 可變長度數組堆棧上創建。 但是任何malloc分配的內存都將在堆上創建。

始終在編譯時評估Sizeof。 在多傳遞編譯器生成符號表時,編譯器必須確定聲明的每個符號的大小,以進一步生成中間代碼。 因此,代碼中的所有sizeof引用都會替換確切的值。 在中間代碼生成階段,所有運算符,語句都轉換為正確的中間代碼(ASM /其他格式)。 最后,m / c代碼生成階段將其轉換為機器代碼。

上面討論的一些討論與sizeof相關的動態分配根本不在上下文中。 任何對size(* p)的引用,其中p是任何數據類型的指針,編譯器只找到* p的數據類型並替換它的大小,而不是檢查分配塊的MCB頭以查看分配的內容內存大小。 它不是在運行時。 例如double * p; sizeof(* p)仍然可以在不為指針p分配任何內存的情況下完成。 這怎么可能?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM