程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C語言其實不簡單:sizeof

C語言其實不簡單:sizeof

編輯:關於C語言

C語言其實不簡單:sizeof


問:C語言中一共有多少個關鍵字?

答:32個。

答不上來的沒關系,很正常,我們玩的是程序的藝術,而不是背數字。不過這個特殊的數字1<<5也是很好記的-.-。


問:sizeof是函數還是關鍵字?

第一次看到這個問題,你可能會覺得有點莫名其妙,sizeof當然是函數了,因為sizeof後面都跟了個括號,這顯然是函數的象征。但是既然我這麼問了,你可能也猜到了,sizeof不是個函數,它是個關鍵字!長期以來由於sizeof的"標准用法",導致sizeof極容易被理解為一個函數。嘗試運行下面的代碼:

#include 

int main()
{
    int num = 5;
    printf("%d\n", sizeof(num));
    printf("%d\n", sizeof(int));
    printf("%d\n", sizeof num);
    getchar();
    return 0;
}

sizeof num居然也能正確輸出4,可見它真的不是函數。不過sizeof int就是錯誤的了,它會產生如下錯誤:

error: expected primary-expression before "int"
因為int前面只能跟auto、unsigned等,況且sizeof int要怎麼來理解?是想計算大小呢?還是想表示"sizeof"類型的int變量呢。

查閱相關資料後總結如下:

當要計算變量的大小,例如基本類型(int、double)的變量,結構體變量(實例)時,可以不用括號,

當要計算一個類型時,不能省略括號。

不管什麼場合都加上個括號,一是統一,而是能使程序可讀性更強,且不易出錯。我的目的並不是為了省略這個括號,省略了並不會讓事情變得更好。我所想要表達的是sizeof的另一方面:因為現在我們知道了sizeof不是函數而是關鍵字,所以其本質也就完全不同了。函數是在運行時確定的,而關鍵字是在編譯時確定的。區別的話,嘗試運行如下程序:

#include 

int main()
{
    int cc[10];
    printf("%d\n", sizeof cc[999999999]);
    getchar();
    return 0;
}

上面的程序並不會出錯,而是正確輸出了4。並不是因為sizeof真的去找相對於cc首地址偏移999999999個位置的那個內存,正如上文所述,sizeof在編譯時確定,所以它根據cc[X]的類型來確定大小。因為sizeof沒有去訪問這些地址,所以上面程序語法上沒有任何問題,只不過邏輯上來說好像沒什麼實際意義。你能不能想到一個能證明sizeof真的沒去"執行"括號裡的東西呢?其實挺簡單,試試運行如下代碼:

printf("%d\n", sizeof(printf("hactrox")));
其結果為4,而且"hactrox並沒有被輸出!沒被輸出說明sizeof真的沒有去調用括號裡的東西,但是為什麼是4呢?因為sizeof是根據類型來確定的,對於printf或者是函數,sizeof以其返回值類型來確定。因為printf返回輸出字符的數量,這個數量是int類型的,所以就相當於sizeof(int),所以是4。可能你還不知道printf的這個特性,試試運行以下代碼:

#include 
int main()
{
	int num = printf("hactrox\n");
    printf("%d\n", num);
    getchar();
    return 0;
}
一個更直接的例子如下:

#include 

int fun()
{
    printf("hactrox");
    return 5;
}

int main()
{
    printf("%d\n", sizeof(fun())); // 函數沒有被執行,根據其返回值類型從而輸出4

    getchar();
    return 0;
}

關於sizeof還有一個需要注意的地方。試試在腦海中執行下面的程序,得出一個結果以後再去運行它:

#include 

#define SIZE_OF_ARRAY (sizeof(array) / sizeof(array[0]))

int main()
{
    int array[] = {1, 2, 3, 4, 5};

    for(int d = -1; d < (SIZE_OF_ARRAY-1); d++)
        printf("%d\n", array[d+1]);
    
    printf("END\n");
    getchar();
    return 0;
}
是不是跟你想的不太一樣?為什麼數組一個都沒輸出?原因就在於sizeof返回的是unsigned int,當int與unsigned int比較的時候,int是要轉成unsigned int的,當int <0的時候,這種強制轉換自然也就悲劇了,其結果是MaxValue(unsigned int)-abs(int),那麼當d = -1的時候,自然就轉變成一個相當巨大的數了,for循環當然也就不執行了。

#include 

int main()
{
    int a = -1;
    unsigned int b = 10000;
    if(a > b)
        printf("a > b\n");
    else
        printf("a < b\n");
    
    a = (unsigned int)a;
    printf("%u\n", a);  // unsigned int要用%u輸出而不要習慣地寫成%d
    
    getchar();
    return 0;
}

最後,因為剛才提到了unsigned int的最大值,C語言中想要輸出int或是unsigned int的最大值要怎麼辦呢?有個簡單的小技巧:

#include 

int main()
{
    printf("Max value of unsigned int is: %u\n", ~(unsigned int)0);       // 結果只能用%u表示
    printf("Max value of int is: %d\n", ~(unsigned int)0 >>1);   // 結果用%d, %u表示均可 
    getchar();
    return 0;
}


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved