2011-11-10 28 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的大小并不意外。 –

相关问题