7

我正在尝试这段代码。

#include <stdio.h>
#include <stdlib.h>
#define LOWER 0
#define UPPER 300

int main()
{
    printf("%d %f",LOWER,UPPER);
    return 0;
}

我读了一些答案,它说定义的常量没有类型,也没有分配任何内存。那么,如果我在 printf() 中指定不同的类型说明符,为什么会出现错误?

4

4 回答 4

4

在您的示例中,两者都作为 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 intint是不同的位宽及其 UB。

底线:如果您将预处理器宏传递到可变参数列表中,例如printf()对推送的数据有大小预期(例如由格式字符串指定),您最好确保您推送的内容是预期的。

于 2012-10-31T16:38:32.303 回答
3

在这种情况下,类型是文字常量的类型。0和都是300适合 的整数常量int,所以它们的类型是int

于 2012-10-31T16:30:42.030 回答
1

它是无类型的;只需将其视为源的文本替换:

printf("%d %f", 0, 300);
于 2012-10-31T16:30:27.473 回答
1

#define是一个预处理器指令。编译后不存在。相反,相应的值将在代码中被替换。在这种情况下,宏扩展后正在编译的实际代码是

//header stdio.h
//header stdlib.h


int main()
{
    printf("%d %f",0,300);
    return 0;
}

是的,在这种情况下,0,300 都是整数。!

于 2012-10-31T16:33:14.733 回答