我正在尝试这段代码。
#include <stdio.h>
#include <stdlib.h>
#define LOWER 0
#define UPPER 300
int main()
{
printf("%d %f",LOWER,UPPER);
return 0;
}
我读了一些答案,它说定义的常量没有类型,也没有分配任何内存。那么,如果我在 printf() 中指定不同的类型说明符,为什么会出现错误?
我正在尝试这段代码。
#include <stdio.h>
#include <stdlib.h>
#define LOWER 0
#define UPPER 300
int main()
{
printf("%d %f",LOWER,UPPER);
return 0;
}
我读了一些答案,它说定义的常量没有类型,也没有分配任何内存。那么,如果我在 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;
}
在这两种情况下,这些都是在编译之前被替换的预处理器宏。请注意,如果不能将 UPPER 提升为 a float
,您将收到编译器错误,这是一件好事。如果可以,它将是,并且printf()
将找到打印所需内容所需的字节。int
和 LOWER 分别也是如此。上面的printf经过预处理后会退化成这样:
printf("%d %f", (int)0, (float)300);
现在想象你的宏被声明为:
#define LOWER 100.0
#define UPPER 300.0
预处理后原件printf()
将呈现为:
printf("%d %f", 100.0, 300.0);
这似乎是对的,但是 100.0 浮点数真的会被%d
格式字符串处理程序正确切除printf()
吗?确保。做我们之前做的:
printf("%d %f", (int)LOWER, (float)UPPER);
现在预处理为:
printf("%d %f", (int)100.0, (float)300.0);
您可能会在 float-to-int 强制转换时收到编译器警告,但可能不会。除非你想掷骰子,你传递的东西的大小是字节大小的,printf()
你需要确保一切都匹配。当格式说明符期望一件事时,这可能会特别令人沮丧,传入不同的东西,但它似乎一切正常,但神秘地只在某些平台上:
printf("%ld\n", UPPER);
这可能“有效”,但如果有效,那只是因为 a long int
和 a int
在您的平台上的大小相同。将此代码移动到一个平台,其中long int
和int
是不同的位宽及其 UB。
底线:如果您将预处理器宏传递到可变参数列表中,例如printf()
对推送的数据有大小预期(例如由格式字符串指定),您最好确保您推送的内容是预期的。
在这种情况下,类型是文字常量的类型。0
和都是300
适合 的整数常量int
,所以它们的类型是int
。
它是无类型的;只需将其视为源的文本替换:
printf("%d %f", 0, 300);
#define
是一个预处理器指令。编译后不存在。相反,相应的值将在代码中被替换。在这种情况下,宏扩展后正在编译的实际代码是
//header stdio.h
//header stdlib.h
int main()
{
printf("%d %f",0,300);
return 0;
}
是的,在这种情况下,0,300 都是整数。!