11

即使经过多次谷歌搜索,我对什么是 C 中的常量表达式和不是 C 中的常量表达式有点困惑。您能否提供一个示例,说明哪些是 C 中的常量表达式,哪些不是?

4

6 回答 6

18

可以在编译时计算常量表达式。这意味着它没有变量。例如:

5 + 7 / 3

是一个常数表达式。就像是:

5 + someNumber / 3

不是,假设someNumber是一个变量(即,它本身不是编译时常量)。

于 2010-09-20T21:11:30.047 回答
15

常量表达式还有另一个微妙之处。有些东西编译器知道,但预处理器不知道。

例如(24*60*60),两者都可以计算,但sizeof struct foo只有编译器知道。如果您尝试验证 astruct是否定义为满足外部要求的大小,或者其成员是否映射到外部指定的偏移量,则此区别可能很重要。(这种用例经常出现在编写设备驱动程序时,其中struct描述的设备寄存器布置在内存空间中。)

在那种情况下,您不能简单地说#if (sizeof(struct UART) == 12)因为预处理器在编译之前运行,并且根本无法知道任何类型的大小。然而,它是一个常量表达式,可以作为全局变量的初始值设定项(例如int UARTwords = sizeof(struct UART) / sizeof(short);),或声明数组的大小(例如unsigned char UARTmirror[sizeof(struct UART)];

于 2010-09-20T21:22:48.317 回答
5

似乎没有人提到另一种常量表达式:地址常量。具有静态存储持续时间的对象的地址是一个地址常量,因此您可以在文件范围内执行此类操作:

char x;
char *p = &x;

字符串字面量定义具有静态存储持续时间的数组,因此这条规则也是您可以在文件范围内执行此操作的原因:

char *s = "foobar";
于 2010-09-21T00:27:30.170 回答
3

任何单值文字都是常量表达式。

3     0.0f    '\n'

(字符串文字很奇怪,因为它们实际上是数组。似乎"hello"并不是一个真正的常量,因为它最终必须被链接等等,并且地址和内容可以在运行时改变。)

大多数应用于常量或类型的运算符(sizeof、casts 等)都是常量表达式。

sizeof(char)
(byte) 15

任何只涉及常量表达式的表达式本身也是一个常量表达式。

15 + 3
0.0f + 0.0f
sizeof(char)

任何涉及函数调用或非常量表达式的表达式通常都不是常量表达式。

strlen("hello")
fifteen + x

任何宏作为常量表达式的状态取决于它扩展为什么。

/* Always a constant */
#define FIFTEEN 15

/* Only constant if (x) is
#define htons(x)  (( ((x) >> 8) | ((x) << 8) ) & 0xffff) 

/* Never constant */
#define X_LENGTH  strlen(x)

我最初在这里有一些关于const标识符的东西,但我对此进行了测试,显然它不适用于 C. const,奇怪的是,它没有声明常量(至少,不是那些足以在switch语句中使用的“常量”)。然而,在 C++ 中,它确实如此。

于 2010-09-20T21:26:34.103 回答
2

另一个有趣的小问题:在 C 中,“enum”的值是一个常量,但只能在“enum”声明完成后使用。例如,以下内容在标准 C 中是不可接受的,但在 C++ 中是可以接受的:

枚举 {foo=19, bar, boz=bar+5;};

可以重写:

枚举 {foo=19, bar}; 枚举 {boz=bar+5;};

尽管这最终会定义多种不同的枚举类型,而不是包含所有值的枚举类型。

于 2010-09-20T21:44:42.280 回答
2

integral character constants作为'a''\n'是编译器识别的常量。他们有类型int

于 2010-09-20T22:06:36.193 回答