c - 预处理器常量溢出?

标签 c c-preprocessor

我使用 Arduino Uno(16 位 int )并且:

#define DT 49
#define DT_MICRO ((DT) * 1000)
...
while (val<DT_MICRO){/*something*/}

哪个给

49
-16536

如果我使用Serial.print(DT);打印它们。为什么?我期望 49000。为什么有负数?如果我(在代码内)使用 Serial.print(DT*1000),也会发生同样的情况。

使用

DT 49L
and DT_MICRO (DT*1000L)

按预期工作。感谢您的澄清。

最佳答案

除了#if指令之外,预处理器不执行算术运算,仅执行文本替换。在编译器的后续阶段看到它之前,代码中出现的任何 DT_MICRO 都会被序列 ((49) * 1000) 替换。

常量491000的类型为int。 (更一般地,整数常量的类型为 intlong intlong long int,具体取决于其值;49 1000 保证适合 int,所以这就是它们的类型。)

因此,表达式 ((49)*1000) 也是 int 类型。对于表达式(与常量相反),类型不受值的影响。如果 49,000 太大而无法放入 int,则表达式会溢出。

类型 int 要求至少为 16 位,上限至少为 32767。现在更常见的是 32 位,上限为 2,147,483,647 ( 231-1)。因此,如果 int 是 16 位,则 DT_MICRO 具有未定义的行为,但很可能评估为 -16536,这就是您所看到的。如果 int 为 32 位,则 DT_MICRO 的计算结果恰好为 49000

至于为什么您会看到该负值,您没有向我们提供足够的信息来确定。你说你“打印”了这个值,但是怎么打印呢?正确的打印方法是:

printf("%d\n", DT_MICRO);

但是您还可以做很多其他事情。

如果您需要确保 DT_MICRO 的类型足够大以保存其值,您可以将定义更改为:

#define DT 49L
#define DT_MICRO (DT * 1000L)

(请注意,只要 DT 定义正确,DT 周围的额外括号就不是必需的)。这会导致它的类型为 long,至少为 32 位,您可以使用以下命令打印它:

printf("%ld\n", DT_MICRO);

关于c - 预处理器常量溢出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25098959/

相关文章:

c - 用汇编语言解释这一行?

我可以在编译 C 代码期间看到定义的宏吗?

难道我们不能为#define写一个可执行语句吗?

C:如何区分字符串和整数?输出可以很好地打印整数,但不能打印字符串

c - CC/GCC 但不是 G++ (C/SDL2/Linux) 的奇怪段错误

c - 宏重新定义的合法用例

c - C stdlib 函数中的抽象格式说明符(例如 printf、scanf)

c++ - 组合字符串文字和整数常量

C: 我怎样才能改变变量写入的寄存器?

c - 使用 pthread_exit 和 pthread_join。 pthread_exit 不会终止调用函数