首頁 > 軟體

聊聊C語言中sizeof運運算元的一個陷阱

2022-11-07 14:00:31

sizeof運運算元通常用於獲取變數或型別所佔記憶體的大小(單位是位元組)

#include <stdio.h>
 
struct D{
    char a;
    int b;
};
 
int main()
{
    int a = 0;
    struct D d;
    printf("sizeof(a)=%ldn", sizeof(a));
    printf("sizeof(int)=%ldn", sizeof(int));
    printf("sizeof(d)=%ldn", sizeof(d));
    printf("sizeof(struct D)=%ldn", sizeof(struct D));
    return 0;
}

執行程式輸出:

sizeof(a)=4
sizeof(int)=4
sizeof(d)=8
sizeof(struct D)=8

使用此特性可以結合memset,對資料結構進行初始化:

#include <stdio.h>
#include <string.h>
 
struct D{
    char a;
    int b;
};
 
int main()
{
	D d;
	printf("before init:a=%d, b=%dn", d.a, d.b);
	memset(&d, 0, sizeof(d));
	printf("after init:a=%d, b=%dn", d.a, d.b);
    return 0;
}

執行程式輸出:

before init:a=16, b=0
after init:a=0, b=0

不過在使用sizeof時需要注意,對於指標型別的變數,只會求值指標的大小,不會求值其指向內容的大小:

#include <stdio.h>
 
int main()
{
    char str[10] = {0};
    char* pStr = str;
    printf("sizeof(str)=%ldn", sizeof(str));
    printf("sizeof(pStr)=%ldn", sizeof(pStr));
    return 0;
}

執行程式輸出:

sizeof(str)=10
sizeof(pStr)=8

這對於通過函數引數進行sizeof求值是一個陷阱:

#include <stdio.h>
#include <string.h>
 
void f(char *pStr)
{
	memset(pStr, 'a', sizeof(pStr));
	printf("pStr:%s sizeof(pStr)=%ldn", pStr, sizeof(pStr));
}
 
int main()
{
    char str[10] = "123456789";
    printf("str:%s sizeof(str)=%ldn", str, sizeof(str));
    f(str);
    return 0;
}

執行程式輸出:

str:123456789 sizeof(str)=10
pStr:aaaaaaaa9 sizeof(pStr)=8

可見,在函數f內,通過指標pStr求值sizeof,獲得的是指標的大小(64位元系統上位8個位元組),如果依據此指來初始化str,那麼只能操作8個位元組,也就導致了呼叫函數f後,str進入了一種混亂的狀態,其內容為:aaaaaaaa9

Sizeof的作用非常簡單:求物件或者型別的大小。然而sizeof又非常複雜,它涉及到很多特殊情況,本篇把這些情況分門別類,總結出了sizeof的10個特性:

(0)sizeof是運運算元,不是函數;

(1)sizeof不能求得void型別的長度;

(2)sizeof能求得void型別的指標的長度;

(3)sizeof能求得靜態分配記憶體的陣列的長度!

(4)sizeof不能求得動態分配的記憶體的大小!

(5)sizeof不能對不完整的陣列求長度;

(6)當表示式作為sizeof的運算元時,它返回表示式的計算結果的型別大小,但是它不對錶示式求值!

(7)sizeof可以對函數呼叫求大小,並且求得的大小等於返回型別的大小,但是不執行函數體!

(8)sizeof求得的結構體(及其物件)的大小並不等於各個資料成員物件的大小之和!

(9)sizeof不能用於求結構體的位域成員的大小,但是可以求得包含位域成員的結構體的大小!

概述:

Sizeof是C/C++中的關鍵字,它是一個運運算元,其作用是取得一個物件(資料型別或者資料物件)的長度(即佔用記憶體的大小,以byte為單位)。其中型別包含基本資料型別(不包括void)、使用者自定義型別(結構體、類)、函數型別。資料物件是指用前面提到的型別定義的普通變數和指標變數(包含void指標)。不同型別的資料的大小在不同的平臺下有所區別,但是c標準規定所有編譯平臺都應該保證sizeof(char)等於1。關於sizeof的更多概述你可以在msdn總輸入sizeof進行查詢。

總結

到此這篇關於C語言中sizeof運運算元的一個陷阱的文章就介紹到這了,更多相關C語言sizeof運運算元陷阱內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com