定义常量的数据类型是什么?

时间:2012-10-31 16:28:31

标签: c

我正在尝试这段代码。

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

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

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

4 个答案:

答案 0 :(得分:3)

在这种情况下,类型是文字常量的类型。 0300都是适合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 intint不同位宽和UB一直的平台。

结论:如果您正在将预处理器宏传递给可变参数列表,例如printf()等对推送数据有大小期望的事物(例如格式字符串所指定),那么最好确定一下“推动是预期的。”

答案 2 :(得分:1)

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

printf("%d %f", 0, 300);

答案 3 :(得分:1)

#definepreprocessor directive。编译后它不存在。而是在代码中替换相应的值。在这种情况下,宏扩展后正在编译的实际代码是

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


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

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