2008-10-27 70 views
40

我正在寻找将预处理器令牌转换为字符串的方法。将预处理器令牌转换为字符串

具体来说,我在什么地方了:

#define MAX_LEN 16 

,我想用它来防止缓冲区溢出:

char val[MAX_LEN+1]; // room for \0 
sscanf(buf, "%"MAX_LEN"s", val); 

我打开其他的方法来完成同样的事情,但只有标准库。

+0

http://stackoverflow.com/questions/195975/how-to-make-a-char-string-from-ac-macros-value – 2015-10-05 13:43:46

+0

[C宏创建字符串](http://堆栈溢出。com/questions/798221/c-macros-to-create-strings) – rjstelling 2015-10-06 10:33:35

回答

78

看到http://www.decompile.com/cpp/faq/file_and_line_error_string.htm 明确:

#define STRINGIFY(x) #x 
#define TOSTRING(x) STRINGIFY(x) 
#define AT __FILE__ ":" TOSTRING(__LINE__) 

所以你的问题是可以解决这样做 sscanf(buf, "%" TOSTRING(MAX_LEN) "s", val);

+0

为什么级联2个宏?不会是一个足够的TOSTRING? – 2017-10-05 12:52:11

19

我在网上找到了答案。

#define VERSION_MAJOR 4 
#define VERSION_MINOR 47 

#define VERSION_STRING "v" #VERSION_MAJOR "." #VERSION_MINOR 

以上不工作,但希望 说明我想怎样做, 即让VERSION_STRING最终成为 “v4.47”。

生成适当的数字形式 使用类似

#define VERSION_MAJOR 4 
#define VERSION_MINOR 47 

#define STRINGIZE2(s) #s 
#define STRINGIZE(s) STRINGIZE2(s) 
#define VERSION_STRING "v" STRINGIZE(VERSION_MAJOR) \ 
"." STRINGIZE(VERSION_MINOR) 

#include <stdio.h> 
int main() { 
    printf ("%s\n", VERSION_STRING); 
    return 0; 
} 
+5

“STRINGIZE”听起来很糟糕.. – Blindy 2010-04-25 20:06:02

4

这已经有一段时间,但这应该工作:

sscanf(buf, "%" #MAX_LEN "s", val); 

如果没有,就需要“双重扩张”把戏:

#define STR1(x) #x 
#define STR(x) STR1(x) 
sscanf(buf, "%" STR(MAX_LEN) "s", val); 
+1

第一个不行; #在宏扩展中对宏参数进行字符串化。第二个将起作用。 – 2008-10-27 15:55:14

2

您应该使用双膨胀字串宏伎俩。或者只是有一个

#define MAX_LEN 16 
#define MAX_LEN_S "16" 

char val[MAX_LEN+1]; 
sscanf(buf, "%"MAX_LEN_S"s", val); 

并保持它的同步。 (这有点麻烦,但只要定义彼此相邻,你可能会记得。)

其实,在这种特殊情况下,不会有strncpy就够了吗?

strncpy(val, buf, MAX_LEN); 
val[MAX_LEN] = '\0'; 

如果是printf,不过,这将是更容易:

sprintf(buf, "%.*s", MAX_LEN, val); 
1

虽然上述一些“工作”,我个人倒只用一个简单的字符串API,而不是dreck的建议来自libc。有许多便携式API,其中一些还针对易于包含在您的项目中进行了优化...有些像ustr有小的空间开销并支持堆栈变量。