我正在寻找一种将预处理器令牌转换为字符串的方法。
具体来说,我在某处:
#define MAX_LEN 16
我想用它来防止缓冲区溢出:
char val[MAX_LEN+1]; // room for \0
sscanf(buf, "%"MAX_LEN"s", val);
我愿意采用其他方式来完成同一件事,但仅限于标准库。
我正在寻找一种将预处理器令牌转换为字符串的方法。
具体来说,我在某处:
#define MAX_LEN 16
我想用它来防止缓冲区溢出:
char val[MAX_LEN+1]; // room for \0
sscanf(buf, "%"MAX_LEN"s", val);
我愿意采用其他方式来完成同一件事,但仅限于标准库。
Answers:
具体参见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);
"%" "MAX_LEN" "%"
产生第二个宏会导致令牌值被粘贴,例如,"16"
因为该TOSTRING
宏使最终代码等效于STRINGIFY(16)
。
我在网上找到了答案。
#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; }
您应该使用双扩展字符串化宏技巧。或者只是有一个
#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);
我的两分钱。
#define MAX_LEN 16
#define AUX_VALUE(x) x
#define QUOTATION_VALUE() "
#define STRINGIFY(x) #x //Ok in all.
//#define STRINGIFY(x) QUOTATION_VALUE()AUX_VALUE(x)QUOTATION_VALUE() //Ok only in VC++
std::string str = STRINGIFY(MAX_LEN);
const char* str2 = STRINGIFY(MAX_LEN);
sscanf(buf, "%" STRINGIFY(MAX_LEN) "s", val);