2014-10-05 40 views
3

我試圖確保我明白這裏隱藏的假設是什麼。在結構體中的「char」之後是否有零字節?

此處的代碼給出了正確的結果。

#include <stdio.h> 
#include <stdlib.h> 

struct branch 
{ 
    char flag;  //value 
    struct branch *l; //left child 
    struct branch *r; //right child 
}; 

struct branch c={'c',NULL,NULL}; 
struct branch e={'e',NULL,NULL}; 
struct branch f={'f',NULL,NULL}; 
struct branch b={'b',&c,NULL}; 
struct branch d={'d',&e,&f}; 
struct branch a={'a',&b,&d}; 

void preorder(struct branch* t) 
{ 
    printf(&t->flag); //Seems ugly and errorprone 
    if(t->l) preorder(t->l); 
    if(t->r) preorder(t->r); 
} 

int main() 
{ 
    preorder(&a); 
} 

輸出,如預期,是abcdef

有人可以證實我的懷疑,認爲這隻能是因爲兩件事情:

  1. 結構成員得到在n字節邊界對齊(N! = 1)(n = 4,看起來,當詢問sizeof() - s)
  2. 第一個成員(它是一個char)未使用的字節直到n字節邊界爲零。

我沒有看到printf工作正常的其他解釋,否則,因爲它期望一個零終止的char []。此外,做這樣的事情是明智的(在單目標嵌入式代碼情況之外,其中優化可能超過可讀性和可移植性問題),也就是說,這些假設或多或少是普遍真實的嗎?

第一週間歇性地與C打交道,所以我很綠。

+1

'的printf(T->標誌)保證假設;'確實是醜陋的(它依靠。 .flag字段之後的字符爲nul;這是不能保證的)'printf(「%c」,t-> flag);'可能是標準的方式。 – wildplasser 2014-10-05 10:47:31

+0

我的第一個膝蓋反射是它稍微快了一點(我跑了一次,而%c版本以4倍的時間完成)。我再次嘗試,結果是早先的結果是虛假的。我猜這樣做沒有什麼可勝利的。 – Jostikas 2014-10-05 12:41:27

+0

出於好奇:這段代碼來自哪裏?我沒有理由不正確地使用'printf'(正如Wildplasser所建議的),或者使用'putchar'。 – mafso 2014-10-05 12:42:34

回答

2

要驗證你的假設,你可以在運行時使用調試器或檢查代碼使用一些printf。

例如,使用:

char *ptr=(char *)&t; 
    printf("%02X %02X %02X %02X\n",ptr[0],ptr[1],ptr[2],ptr[3]); 

事實上你確定的假設是非常往往是真的,但你不能依靠他們。我肯定會說,

printf(&t->flag); 

顯然是錯誤的,因爲它依賴於不被standard.tt

+0

我只能驗證可用於我的架構,如果它是常見的,我很可能會發現它們是真實的。有時候對這些事情有經驗的看法是很好的。我認爲可能會有一些提速的機會,但看起來差不多。 – Jostikas 2014-10-05 12:52:22

+0

@ Remo.D,因此它不是「明顯錯誤的,因爲它依賴於標準不能保證的假設」,但它不是可移植的,如果想編寫與標準相關的代碼,則顯然是錯誤的。如果他爲了這個特定的環境寫了他所有的生活,那麼也許它根本就沒有錯? – 4pie0 2014-10-05 13:30:54

+0

@ 0d0a好吧,唯一的(幾乎)可以接受的情況是,如果這只是在相同的操作系統(同樣的版本)上再次編譯相同的編譯器版本等。如果它編譯和測試後將以二進制形式生活不會皺眉頭:) – 2014-10-06 08:38:14

2

可以證明1和自己2(我用64位,這就是爲什麼在結構排列的都是8個字節)

objdump ./main -s -j .data 

Contents of section .data: 
601030 00000000 00000000 00000000 00000000 ................ 
601040 63000000 00000000 00000000 00000000 c............... 
601050 00000000 00000000 00000000 00000000 ................ 
601060 65000000 00000000 00000000 00000000 e............... 
601070 00000000 00000000 00000000 00000000 ................ 
601080 66000000 00000000 00000000 00000000 f............... 
601090 00000000 00000000 00000000 00000000 ................ 
6010a0 62000000 00000000 40106000 00000000 [email protected]`..... 
6010b0 00000000 00000000 00000000 00000000 ................ 
6010c0 64000000 00000000 60106000 00000000 d.......`.`..... 
6010d0 80106000 00000000 00000000 00000000 ..`............. 
6010e0 61000000 00000000 a0106000 00000000 a.........`..... 
6010f0 c0106000 00000000     ..`..... 
+0

謝謝!我不知道!同樣對不起,我正在接受Remo D.-s的回答,因爲他也回答了第二部分。我會upvote,但似乎我沒有足夠的聲譽,但即使如此:) – Jostikas 2014-10-05 12:46:58

+0

@Jostikas現在你有 – 4pie0 2014-10-05 13:25:10

相關問題