C語言:關於 sizeof

2021-02-20 泰曉科技

歡迎點擊上方藍色「泰曉科技」關注我們

作者:文平波

圖片來源自網絡

sizeof 是 C 中的一個關鍵字,用來計算類型或者表達式的大小。

今天在看書的時候,碰到一個問題,是說 sizeof 無法計算一個數組的大小,在編譯的時候,就出現錯誤。不解,自己嘗試著編寫了一個例子,果然出現這個錯誤:

錯誤:invalid application of 'sizeof' to incomplete type 'int[]'

例子如:

f1.h:

extern int array[];
extern int size;
int array2[10];

f1.c:

#include "f1.h"

int array[]={1,2,3};
int size = sizeof(array);

f2.c:

#include "f1.h"
#include "stdio.h"
#define TEST

int main(int argc, char *argv[])
{
    printf("array: %d\n", size);
    
    printf("array2: %d\n", sizeof(array2));

    return 0;
}

可以看到,在 f2.c 中,第二個被注釋的 printf 是編譯不過去的,第三個正常。

WHY ?

因為 sizeof 是在編譯的時候來處理每個對象的大小,而編譯的時候是以一個文件 ( 編譯單元 ) 為單位進行編譯的。所以在處理一個編譯單元的時候,編譯器是無法從另外一個文件來獲得一個非完全聲明類型的大小的。這也是為什麼錯誤提示中有一個 incomplete type 的字眼了。

那麼,什麼是 incomplete type?

在 ISO-IEC 9899 的標準文檔的 6.2.5 中,是這樣來定義類型的:

The meaning of a value stored in an object or returned by a function is determined by the type of the expression used to access it. (An identifier declared to be an object is the simplest such expression; the type is specified in the declaration of the identifier.)

Types are partitioned into object types (types that describe objects) and function types (types that describe functions). At various points within a translation unit an object type may be incomplete (lacking sufficient information to determine the size of objects of that type) or complete (having sufficient information)

從上可以看出類型被分為:對象類型、函數類型。而在一個翻譯單元中,對象類型可能是完全的,或者非完全的。

也就是說非完全類型是對象類型的一個特殊類,而什麼時候,一個對象類型是不完全的呢?

標準文檔是這麼說的:缺乏足夠的信息來決定一個對象類型的大小

可能說這麼多,大家有點迷糊了,下面引用一下 IBM 在 XL C/C++ (V6.0) 的規範文檔中,把如下的類型歸類為非完全類型:

void 類型 eg. void *ptr;

沒有指明大小的數組 eg. extern int array[];

數組中的元素是非完全類型

沒有定義的結構體、union 和枚舉類型 eg. struct test;

沒有定義的類指針;

只聲明,無定義的類 eg. class test;

其實, incomplete type 一個經常的用處,那就是隱藏一些類型的細節,比如,在頭文件中聲明一個 struct test; ,然後其他程序如果要使用這個結構體,那就包含這個頭文件,但是它們無法知道這個結構體內部的細節,也就無法訪問結構體內部成員,當然,更加不能用 sizeof 。但是對於那些,只是做一個傳遞的外部函數,這些足夠了。

所以,以後用 sizeof 的時候,還是注意一下。

註:由於微信公眾號無法在正文中嵌入外部連結,所以這裡的文章為增強閱讀體驗移去了部分外部連結。如果您希望獲取正文中的外部連結請移步本文文末左下方點擊 「閱讀原文」。


上課啦!上課啦!

近日,泰曉科技與閱碼場強強聯合,首度推出程式設計師自我修養之 「360° 剖析 Linux ELF」在線視頻課程。如果您想進一步提升自己的實力,掌握更多有關 Linux 環境下程序編譯、連結、運行的底層奧秘,歡迎點擊  "課程介紹"  進入相關頁面了解更多訊息。

關注「泰曉科技」!點「在看」

~讚賞歸·原創作者·所有~

相關焦點

  • 理解c語言的sizeof
    c語言有很多用起來需要特別注意的地方,我們(計算機學習微信公眾號:jsj_xx)以後會分析其中有使用價值的點。今天我們一起看看sizeof。
  • 詳細解析C語言中的sizeof
    一、sizeof的概念  sizeof是C語言的一種單目操作符,如C語言的其他操作符++、--等。它並不是函數。sizeof操作符以字節形式給出了其操作數的存儲大小。操作數可以是一個表達式或括在括號內的類型名。操作數的存儲大小由操作數的類型決定。
  • 編程基礎-c語言中sizeof用法總結
    1、sizeof是c語言中用來求字節運算符。sizeof用來求一個對象(類型,變量,……)所佔的內存大小(以字節為單位)。char *p = NULL;sizeof(p) == 4;typeof(p) == char *sizeof(p) == sizeof(char *) == 4sizeof(*p) ==
  • 【C語言經典編程技術】C語言中union與struct的區別及sizeof的計算方式
    C語言中union與struct的區別在C語言中結構體和聯合具有細微差別,特別是使用sizeof()對其求大小時,許多剛剛接觸
  • 關於C語言sizeof操作符的使用
    如果sizeof操作符後面跟著一個基本變量類型,需要使用().格式控制符為 %zd ;例如 sizeof(int);如果sizeof操作符後跟著一個變量的具體名稱,則不需要用();例如int test = 0;
  • c語言不定參數宏INTSIZEOF的由來
    首先,我聲明一下,這篇文章適合想理解c的人群來看的,當然不是說我特別厲害什麼的,因為只是一個小知識點而已,主要是我是從用戶的角度來看的,我這篇文章在我寫完的時候,發現並沒是沒什麼圖片的,沒有什麼興趣點,只有理論的。若是我來看的話,我也不會去看的。
  • C/C++基礎之sizeof使用
    ,前幾天文章C語言指針詳解提到過,指針變量的位寬等於機器字長,機器字長由 CPU 寄存器位數決定。    int A[3][5];    char c[]="abcdef";    double*(*d)[3][6];    cout<<sizeof(A)<<endl;      //輸出60    cout<<sizeof(A[4])<<endl
  • 通俗易懂地告訴你,java語言中為什麼沒有sizeof操作符
    01sizeof()定義sizeof是c語言的一種單目操作符,如c語言的其他操作符++、--等。它並不是函數。sizeof操作符以字節形式給出了其操作數的存儲大小。操作數可以是一個表達式或括在括號內的類型名。操作數的存儲大小由操作數的類型決定。
  • 實例分析C語言中strlen和sizeof的區別
    往期精選區別sizeof
  • 經典C語言面試題:sizeof與strlen的區別
    _u=ukgdp5a7629&id=524088004171】、基本定義1、sizeof是C/C++中的一個運算符,其作用是返回一個對象或者類型在內存中所佔用的字節數。    注意:sizeof後面如果是類型則必須加括號,如 sizeof(char);而如果是變量名則可以不加括號,如 sizeof a; 但是建議使用時  均加上括號。
  • C/C++刁鑽問題各個擊破之細說sizeof
    其中類型包含基本數據類型(不包括void)、用戶自定義類型(結構體、類)、函數類型。數據對象是指用前面提到的類型定義的普通變量和指針變量(包含void指針)。不同類型的數據的大小在不同的平臺下有所區別,但是c標準規定所有編譯平臺都應該保證sizeof(char)等於1。關於sizeof的更多概述你可以在msdn總輸入sizeof進行查詢。看了上面這些,或許你看了沒有多少感覺。
  • C語言全局變量那些事兒
    今天我們就來黑一把C語言,好好展示一下這門經典語言令人抓狂的一面。b大小是4個字節,而foo.c是8個字節,因為sizeof關鍵字是編譯時決議,而源文件中對b類型定義不一樣。=0x%08x\n\tsizeof(b)=%d\n\tset b=%d\n\tc=%d\n",             &b, &c, sizeof b, b, c);         foo();
  • 一起學習C/C++ (7) 分辨sizeof和strlen
    正因為sizeof不是函數,因此我們不把它所要求得長度的對象叫做參數,這也是sizeof不能求得void類型的長度 你無法求出sizeof(void),其實你是無法聲明出void的一個變量的,void指的是一個空類型,空類型你是無法知道變量內存空間大小的,所以你用sizeof去求肯定是不行的。
  • c語言指針與字符數組
    ,字符串的使用在C語言中也是非常重要的,常常會遇到一些操作,如字符串的修改、拷貝、字符串長度等,在物聯網的應用中也尤為突出,物聯網應用中所用的模組,大多是需要使用AT指令的,這就需要對字符串的操作。我們列印出來看一下#include<stdio.h>int main(){ char c[] = "hello"; peintf("size of c = %d\n",sizeof(c)); return 0;}我們列印出來的結果是6明明裡面是5個字符
  • C語言的那些小秘密之字節對齊
    按照預先的計劃安排,這次應該是寫《C語言的那些小秘密之鍊表(三)》的,但是我發現如果直接開始講解linux內核鍊表的話,可能有些地方如果我們不在此做一個適當的講解的話,有的讀者看起來可能難以理解,所以就把字節對齊挑出來另寫一篇博客,我在此儘可能的講解完關於字節對齊的內容,希望我的講解對你有所幫助。
  • C語言實操:用C語言實現隨機抽取紙牌
    程序需要用戶指明手機有幾張牌,格式為:Enter number of cards in hand:____your hand: _二、原理1.使用庫函數time函數返回當前時間,用一個數表示,srand函數初始化C語言的隨機數生成器。
  • 門外漢入門級C語言學習筆記第二課
    來,讓我們繼續對world say hello~先讓我們看看原始碼:在VC++6.0下的顯示是這樣的以下我們進行詳細分解:第一行#include<stdio.h>有#都是預處理,關於預處理咱開始就提到過,後面將#define還會在講到的,慢慢理解不著急這個不是大毛病。
  • 物聯網開發筆記——嵌入式開發之Linux系統中C語言數據類型
    嵌入式開發學習C語言打下基礎。本節介紹《Linux系統中C語言數據類型》。1 數據類型分類short、int、long、char、float、double 這六個關鍵字代表C 語言裡的六種基本數據類型。
  • 剖析c語言結構體的高級用法(二)
    ,為此我特地下了一個vc++6.0編譯器來做了一下試驗,結果還真是一個字節,不過你要注意的是它是c++後綴名,但是你在vc++6.0(還有vs,這兩個編譯裡不能申明一個空的結構體,必須要有一個結構體成員來才行)寫成c語言程序空結構體的話,它會報錯,在新一點的編譯器裡面就不會報錯(比如dev,gcc)。
  • C 語言程序設計---指針
    上次 C 語言寫到了數組,有些書是先講指針,有些書是先講函數,按照我以前學習 C 語言的順序,以及對 C 語言的理解,學習的順序是這樣的:數組--->指針--->函數,所以本篇文章講解 C 之指針。C 語言是值得好好學習的一門語言,是一門基礎語言,更是我編程入門的語言,其中很多編程思想,至今影響著我,在工作中對我的幫助很大。