2011-07-23 40 views
0

我需要存儲每個數組元素—兩個項目char兩個數組,其中可能包含空字節—,然後仍然能夠使用sizeof()來獲得它們的長度。由於這些值在執行過程中不會改變,我認爲GCC應該能夠處理這個問題。C - sizeof()靜態字符數組內的數組 - 不可能?

下面的代碼:

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

struct name_data { 
    char *name; 
    char *data; 
} name_bins [] = { 
    { "John", "\xAA\xAA\x00\xAA" }, 
    { "Mark", "\xFF\x0A\x00\x33\x01\x01\x03\x04\x04\x05" }, 
}; 

char bin_test[] = "\xFF\x0A\x00\x33\x01\x01\x03\x04\x04\x05"; 

int main() { 
    printf("sizeof(bin_test) = %lu\n", sizeof(bin_test)); 
    printf("sizeof(name_bins[1].data) = %lu\n", sizeof(name_bins[1].data)); 
    exit(0); 
} 

此代碼的輸出是:

sizeof(bin_test) = 11 
sizeof(name_bins[1].data) = 8 

然而,bin_test相當於name_bins[1].data在內容—雖然類型定義是不同— bin_testchar[]names_bins[1].datachar*

有沒有辦法用char[] s來定義name_bins數組? 有沒有辦法強制GCC將此值識別爲靜態常量,並返回實際內容大小與sizeof() —,它已經在編譯時計算出來了?

+0

如果您char'的'陣列可能包含空字節,可以考慮將其定義爲uint8_t'的'爲了清晰的數組。大多數C程序員認爲'char *'是一個指向空終止字符串的指針。 – tomlogic

回答

1

你可以幾乎做你想要的,通過將data的大小作爲單獨的條目存儲:

struct name_data { 
    char *name; 
    char *data; 
    size_t data_size; 
} name_bins[] = { 
    { 
     "John", 
     "\xAA\xAA\x00\xAA", 
     sizeof("\xAA\xAA\x00\xAA") 
    }, { 
     "Mark", 
     "\xFF\x0A\x00\x33\x01\x01\x03\x04\x04\x05", 
     sizeof("\xFF\x0A\x00\x33\x01\x01\x03\x04\x04\x05") 
    } 
}; 

然後:

printf("sizeof(bin_test) = %lu\n", sizeof(bin_test)); 
printf("sizeof(name_bins[1].data) = %lu\n", (unsigned long)name_bins[1].data_size); 

然後,你只需要確保你的name_bins初始化是正確的。你可以在混合折騰宏,以避免重複,雖然自己:

#define BIN(x,y) { (x), (y), sizeof(y) } 

struct name_data { 
    char *name; 
    char *data; 
    size_t data_size; 
} name_bins [] = { 
    BIN("John", "\xAA\xAA\x00\xAA"), 
    BIN("Mark", "\xFF\x0A\x00\x33\x01\x01\x03\x04\x04\x05") 
}; 
+0

感謝您的支持! - 有沒有辦法進一步優化它,以便我可以使用(sizeof([指向上面的值的東西]),而不必重新粘貼的值? – Arkadi

+0

@Arkadi:看到我的更新 –

+0

很好!!!謝謝很多 :) – Arkadi

2

不,這是不可能的。 struct的大小是恆定的(sizeof任何對象name_data總是相同的)。如果可能的話,可以有兩個相同類型的對象,大小不同。

+0

謝謝cnicutar。有沒有另一種方法可以定義一個結構數組,保持上述邏輯並允許使用sizeof()? – Arkadi

+0

@Arkadi我也想知道這樣的事情:) – cnicutar

1

如果您想了解一下您要求編譯器在此處做什麼,您可能會意識到您所要求的內容並不現實。

爲了讓編譯器弄清楚,sizeof(name_bins[1].data)11,那就要確保導致的含sizeof代碼行每一個可能的路徑具有完全相同的狀態,當它涉及到name_bins[1].data對象。

在你給出的簡單例子中,你可能會希望編譯器能夠以某種方式解決這個問題。但是如果你的應用程序變得更復雜呢?編譯器如何知道name_bins[1].data仍然包含"\xFF\x0A\x00\x33\x01\x01\x03\x04\x04\x05"

編輯:從意見的後續行動,你可以創建一個新類型,同時擁有數據和尺寸:

typedef struct ConstByteString { 
    const unsigned char* data; 
    size_t length; 
} ConstByteString; 

,然後使用:

struct name_data { 
    const char* name; 
    ConstByteString data; 
} name_bins [] = { 
    { "John", { "\xAA\xAA\x00\xAA", sizeof("\xAA\xAA\x00\xAA") } }, 
    { "Mark", { "\xFF\x0A\x00\x33\x01\x01\x03\x04\x04\x05", sizeof("\xFF\x0A\x00\x33\x01\x01\x03\x04\x04\x05") } }, 
}; 
+0

感謝Sander--我看到你的觀點,我想也許有辦法告訴GCC這個變量是不可觸摸的(不能改變整個執行流程) - 然後,sizeof應該成爲可能。有什麼辦法可以做到這一點? – Arkadi

+1

@Arkadi:總之:沒有。 'data'是一個'char *',然後'sizeof(name_bins [1] .data)'和sizeof(char *)'相同。或'data'是一個'char'數組,然後'sizeof(name_bins [1] .data)'將返回該數組的總大小(但是sizeof(name_bins [i] .data)'將是相同的每個'我')。爲什麼你需要這個來處理'sizeof'? –

+0

因爲我不能使用strlen(),因爲它可能包含空字節。有沒有辦法定義結構包含2 char []而不是2 char *,這將允許sizeof()的工作? (我沒有辦法完成這件事) – Arkadi