簡體   English   中英

為什么 char 不是單個字符?

[英]Why is char not a single character?

在 Microsoft 的dbcc_name文檔中, dbcc_name的類型定義如下:

char  dbcc_name[1];

但正如這個 StackOverflow 問題所示,它原來是一個包含多個字符的string

char不是16 位值的單個字符嗎? 這是如何運作的?

(我原本以為char是 16 位。大概是因為它在 c# 中的大小。實際上可能是因為我正在查看DEV_BROADCAST_DEVICEINTERFACE_W ,它確實是 2 個字節。)

char不是 16 位值嗎?

在什么平台上? 在大多數平台上(包括所有運行 Windows、AFAIK 的平台), char是 8 位。

這是如何運作的?

類型文檔解釋了這一點:

dbcc_size

此結構的大小,以字節為單位。 這是成員的大小加上 dbcc_name 字符串的實際長度(null 字符由將 dbcc_name 聲明為一個字符數組來說明。)

換句話說, _DEV_BROADCAST_DEVICEINTERFACE_A的定義利用了 arrays 衰減到 C++ 中的指針這一事實,因此具有數組類型的dbcc_name在大多數情況下都可以用作以零結尾的字符串。 實際字符串與_DEV_BROADCAST_DEVICEINTERFACE_A object 連續存儲,地址從dbcc_name的偏移量開始。

值得注意的是,數組 (1) 的大小與其內容的長度無關; 它只是 C++ 中最小的合法 static 數組大小(遺留代碼偶爾使用char[0]類型的結構成員。但是,這是編譯器擴展而不是合法的 C++)。

這就是所謂的“結構黑客”。 這是一個允許您在struct實例中存儲可變大小數據的技巧。

您將最后一個成員設為大小為 1 的數組,如下所示:

struct foo { int i; char c[1] };

假設一個 4 字節int ,這個類型是 5 字節寬(盡管它可能會占用 8 個字節來滿足任何 alignment 要求),並且struct foo的實例看起來像這樣:

   +---+
i: |   |
   +---+
   |   | 
   +---+
   |   |
   +---+
   |   | 
   +---+
c: |   |
   +---+

However, if you allocate memory for it dynamically with malloc or calloc , you can allocate more memory than just what's needed for the struct type and that extra memory will be considered part of the array (since struct elements are guaranteed to be laid out in the聲明的順序和數組類型不強制執行大小)。

struct foo *p = malloc( sizeof *p + strlen( "hello" )); 
p->i = 1;
strcpy( p->c, "hello" );

因此,我們為struct類型(5 個字節)分配了足夠的 memory以及足夠的 memory 來存儲"hello" ,這給了我們(假設 little-endian)

   +---+ ----+
i: | 1 |     |
   +---+     |
   | 0 |     |
   +---+     |
   | 0 |     +---- size of struct foo
   +---+     |
   | 0 |     |
   +---+     |
c: |'h'|     |
   +---+ ----+
   |'e'|     |
   +---+     |
   |'l'|     |
   +---+     |
   |'l'|     +---- Extra memory for "hello"
   +---+     |
   |'o'|     |
   +---+     |
   | 0 |     |
   +---+ ----+

為什么我們將c大小為 1 的數組而不是指針? 如果我們將c指針,例如

struct foo { int i; char *c };

那么這個技巧不起作用,因為所有c可以存儲的是地址,而不是數據。

C 允許“靈活的數組成員”,其中聲明中不需要大小:

struct foo { int i; char c[] };

但是,C++ (尚)不支持此功能,因此您必須指定非零大小。

這是一個非常古老的把戲。

typedef struct 
{
    size_t size;
    char str[1];
} mystring_t;

mystring_t *allocate(size_t size)
{
    return malloc(sizeof(mystring_t) + size -1);
}

然后您可以輕松地重新分配它,因為靈活部分始終位於結構的末尾。

在較新的 C 版本中

typedef struct 
{
    size_t size;
    char str[];
} mystring_t;

或使用 gcc

typedef struct 
{
    size_t size;
    char str[0];
} mystring_t;

暫無
暫無

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

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