我正在尝试这段代码。
#include <stdio.h>
#include <stdlib.h>
#define LOWER 0
#define UPPER 300
int main()
{
printf("%d %f",LOWER,UPPER);
return 0;
}
我读了一些答案,它说定义的常量没有类型,也没有分配任何内存。 那么,如果我在printf()中指定不同的类型说明符,为什么会出错?
答案 0 :(得分:3)
在这种情况下,类型是文字常量的类型。 0
和300
都是适合int
的整数常量,因此其类型为int
。
答案 1 :(得分:3)
在您的示例中,两者都作为int值被推入printf的可变参数列表中。这可能导致格式字符串printf()
中的格式标记与基础类型不匹配。有关未定义行为可能发生的原因,请参阅this post。
看起来很可怕,知道你可以通过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无法升级为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);
看起来似乎是正确的,但是%d
中的printf()
格式字符串处理程序是否真的可以正确删除100.0 float?确保。做我们以前做过的事情:
printf("%d %f", (int)LOWER, (float)UPPER);
现在预处理到:
printf("%d %f", (int)100.0, (float)300.0);
你可能会在float-to-int强制转换中获得编译器警告,你可能不会。除非你想要掷骰子,你传递的大小与printf()
之类的字节大小相同,你需要确保一切都匹配。当格式说明符期望一件事,传递不同的东西时,这可能会特别令人沮丧,但它看起来一切正常,但只是在一些平台上神秘地:
printf("%ld\n", UPPER);
这可能“有效”,但如果确实如此,只有因为 long int
和 int
是相同的您平台上的尺寸。将此代码移至long int
和int
不同位宽和UB一直的平台。
结论:如果您正在将预处理器宏传递给可变参数列表,例如printf()
等对推送数据有大小期望的事物(例如格式字符串所指定),那么最好确定一下“推动是预期的。”
答案 2 :(得分:1)
它是无类型的;只需将其视为源代码的文本替换:
printf("%d %f", 0, 300);
答案 3 :(得分:1)
#define
是preprocessor directive。编译后它不存在。而是在代码中替换相应的值。在这种情况下,宏扩展后正在编译的实际代码是
//header stdio.h
//header stdlib.h
int main()
{
printf("%d %f",0,300);
return 0;
}
是的,在这种情况下,0,300都是整数。 !