我正在做宏的基础知识。我定义了一个宏如下:
#define INTTOSTR(int) #int
将整数转换为字符串。
这个宏是否完美地将整数转换为字符串?我的意思是在某些情况下这个宏会失败吗?
我可以使用此宏来替换itoa()
等标准库函数吗?
例如:
int main()
{
int a=56;
char ch[]=INTTOSTR(56);
char ch1[10];
itoa(56,ch1,10);
printf("%s %s",ch,ch1);
return 0;
}
上述程序按预期工作。
有趣的是,这个宏甚至可以将float
值转换为字符串。
例如:
INTTOSTR(53.5);
效果很好。
直到现在我在我的所有项目中使用itoa
函数将int转换为string。我可以在所有项目中自信地替换itoa
。因为我知道使用宏的开销比函数调用少。
答案 0 :(得分:5)
宏在编译时(准确)编译时执行,因此您可以将源代码中的文字编号转换为字符串,而不是存储在变量中的数字
在您的示例中,INTTOSTR(56)
使用预处理器的字符串化运算符,最终生成"56"
。如果您在变量上调用它,则会获得变量名称,但不会获取其内容。
答案 1 :(得分:2)
在C中,您可以使用 itoa ,或者如果您绝望并希望避免它,请使用 snprintf :
snprintf(my_str, sizeof(int), "%i", my_int);
宏的问题在于您正在考虑常量,但当然,当您需要使用包含整数的变量时,您的宏将被破坏。您的宏将尝试对宏名称进行字符串化,而不是将其保留的值。
如果你对常量很好,你的宏是“好的”,否则就是b0rked。
答案 2 :(得分:1)
你的宏不会将整数转换为字符串,它会将文字转换为字符串文字,这是非常不同的。
文字是代码中任何普通数字或值的定义。当您在整数字面中int x = 10;
10
时,x
是变量而int
是类型。 const char* ten = "10";
还定义了一个文字,在本例中是一个字符串文字,其值为"10"
,另一个名为ten
的变量指向定义此文字的地址。你的宏实际上做的是改变在任何实际编译进行之前表示文字的方式,从整数文字到字符串文字。
因此,实际的更改是在任何编译之前完成的,只是在源代码级别。宏不是函数,不能检查内存,并且您的转换不适用于变量。如果您尝试:
int x = 10;
const char* ten = INTTOSTR(x);
您会非常困惑地发现您的变量ten
实际上会保留值“x”。那是因为x被视为文字,而不是变量。
如果你想看看发生了什么,我建议你让编译器停止预处理,并在代码被实际编译之前看到输出。如果传递-E标志,可以在GCC中执行此操作。
PS。关于浮点值转换的明显“成功”,它只是显示宏的危险:它们不是类型安全的。它不会将53.5视为浮点数,而是将其视为由字符5,3,...表示的标记。和源代码中的5。