2011-11-10 29 views
6

我想編寫一個宏來編寫一個字符串,使用知道字符串文字長度的編譯時優化。但是我需要使用指針來檢測錯誤。如何區分C宏中的char *的常量字符串

這裏就是我的意思是:

void transmit(const char *data, int length); 
#define tx_string(x) transmit((x), sizeof(x) -1) 
void func(char *badmsg) { 
    tx_string("GO"); // ok 
    tx_string(badmsg); // not OK 
} 

隨着第二個呼叫,規模將是廢話(的sizeof指針)。

如果我試圖在字符串字面以外的任何地方使用tx_string,我想產生一個編譯時錯誤。這是使用gcc;有沒有我可以用來做到這一點的gcc東西?

編輯:我使用的數據緩衝區可能包含空值或不能被空值終止。我真的想防止指針被用於此,並防止運行時使用strlen()

編輯2:

下面是這將導致一個問題的例子。 我會發明一個假想的協議,我必須告訴16位微控制器一個地址,使用命令GO後跟16位原始地址(兩個8位字符),我想從地址0開始。

#define GOSEQ "GO\000\000" 

void func(void) { 
    char *bad = GOSEQ; 
    tx_string(GOSEQ); // ok, sends 4 bytes: GO and two zero bytes 
    tx_string(bad); // bad, using runtime strlen sends two characters "GO" 
} 

我覺得肯定有一定的gcc內建檢查。我看到Linux內核源碼使用編譯時區分技巧很多,但是不能很快使用特定的技巧。

到目前爲止,「Windows程序員」的想法看起來不錯,但更有意義的編譯時錯誤將是一個獎金。

回答

9

一般來說,因爲你不能使用指針等字符串連接,也許你可以使用:

#define STRLIT(x) x "" 

如果參數到STRLIT不是一個字符串文字,你會得到一個編譯錯誤。

適應一般到特定的宏:

#define tx_string(x) transmit((x ""), sizeof(x) - 1) 
+0

這看起來像贏家!如果有人想出完美的內置測試或其他內容,我會稍微等一下。 – blueshift

4

你可以這樣做:

#define tx_string(x) transmit(x, strlen(x)) // No need for extra parentheses 

GCC將優化出strlen呼叫,我敢肯定,其他的編譯器也會。不要浪費你的時間在這些東西上。

測試文件:

#include <string.h> 
void transmit(const char *, size_t); 
#define tx_string(x) transmit(x, strlen(x)) 
void func(void) 
{ 
    tx_string("abcdef"); 
} 

得到的組件:

我修剪噪音出來的組裝,這是重要的東西。請注意,它永遠不會調用strlen,相反,它只是使用了數6:

.LC0: 
    .string "abcdef" 

func: 
    movl $6, %esi 
    movl $.LC0, %edi 
    jmp  transmit 
+0

OK,但我可能包含空值的數據緩衝區工作或不被零值終止。我真的想要防止使用指針,並防止運行時strlen()的使用。 – blueshift

+1

@blueshift:在C中,指針和數組可以作爲函數的參數互換。爲什麼你需要防止指針被傳遞?這對我沒有意義。我也不確定爲什麼你需要阻止運行時'strlen'的使用。你能解釋一下嗎? –

+0

@Deitrich Epp:我以前的評論應該解釋它。我會編輯這個問題,使其更清晰。 – blueshift

1
#define tx_string(x) ("i came, i concatenated, i discarded " x, transmit((x), sizeof(x) - 1)) 

不是很完美,因爲有些滑稽可以調用tx_string(+1)

+0

我看到你在那裏做了什麼。偷偷摸摸的。我很驚訝sizeof(+1)編譯。 其實如果丟棄字符串被移動到x的右側,它看起來很不錯..不能立即想到編譯的任何無效。 – blueshift

+0

你是對的,Jonathan Leffler的答案解決了我的小缺陷。與此同時,一些int編譯器的sizeof和int的大小並不意外。 –

相關問題