我正在尝试这段代码.
#include <stdio.h>
#include <stdlib.h>
#define LOWER 0
#define UPPER 300
int main()
{
printf("%d %f",LOWER,UPPER);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我读了一些答案,它说定义的常量没有类型,也没有分配任何内存.那么,如果我在printf()中指定不同的类型说明符,为什么会出错呢?
在您的示例中,两者都作为 int 值推入 printf 的可变参数列表中。这可能会导致格式字符串中的格式标志与printf()基础类型不匹配的问题。请参阅这篇文章,了解可能发生未定义行为的原因。
尽管看起来很可怕,但知道你能从中得到你想要的东西的一种方法printf是这样做:
#include <stdio.h>
#include <stdlib.h>
#define LOWER 0
#define UPPER 300
int main()
{
printf("%d %f", (int)LOWER, (float)UPPER);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,这些都是在编译之前被替换的预处理器宏。请注意,如果 UPPER 无法提升为 a,float您将收到编译器错误,这是一件好事。如果可以,那就会,并且printf()会找到打印它想要的内容所需的字节。int对于和 LOWER也是如此。上面的 printf 在预处理后将退化为:
printf("%d %f", (int)0, (float)300);
Run Code Online (Sandbox Code Playgroud)
现在想象一下您的宏被声明为这样:
#define LOWER 100.0
#define UPPER 300.0
Run Code Online (Sandbox Code Playgroud)
预处理后原图printf()如下:
printf("%d %f", 100.0, 300.0);
Run Code Online (Sandbox Code Playgroud)
这似乎是正确的,但是 100.0 浮点数真的会被%d中的格式字符串处理程序正确删除吗printf()?确保。做我们之前做的事情:
printf("%d %f", (int)LOWER, (float)UPPER);
Run Code Online (Sandbox Code Playgroud)
现在预处理为:
printf("%d %f", (int)100.0, (float)300.0);
Run Code Online (Sandbox Code Playgroud)
您可能会收到有关 float 到 int 转换的编译器警告,也可能不会。除非你想掷骰子,否则你所传递的内容的大小应达到字节大小的预期,例如printf()你需要确保所有内容都匹配。当格式说明符期望一件事,传入不同的东西时,这可能会变得特别令人沮丧,但它似乎一切正常,但仅在某些平台上神秘地工作:
printf("%ld\n", UPPER);
Run Code Online (Sandbox Code Playgroud)
这可能“有效”,但如果有效,那只是因为 a long int 和 a int 在您的平台上大小相同。long int将此代码移至和int具有不同位宽及其 UB 的平台。
底线:如果您将预处理器宏传递到可变参数列表中,例如printf()对要推送的数据有大小预期(例如由格式字符串指定),您最好确保您推送的内容是预期的。