问题
我很好奇是否有任何关于在 C 中进行恒定折叠的保证。
我看过的地方
一个我不知道声誉的网站上的这个链接提出了一个临时评论:
所有 C 编译器都可以折叠宏扩展后出现的整数常量表达式(ANSI C 要求)。
但是我没有在例如 The C Programming Language, second edition 中看到任何内容(我认为它已经彻底更新以说明 ANSI C 的所有细节)。但是在检查索引以获取相关词的引用后,我没有发现任何可以保证这一点的东西。第 38 页和第 209 页特别接近,因为他们说任何可以在编译时计算的表达式都可以在可以使用常量的地方使用(如果我们足够迂腐的话,可能会有一些限制),并且它说这样的表达式“可能”在编译时被评估,而不是“将”/(一些同义词)。
我搜索了这个 C89 最终草案。单词“folding”和“folded”没有产生值的结果,搜索“constant expression”产生了63个匹配,其中我检查了大约一半。感兴趣的主要部分似乎与本书基本相同(它使用单词“ can ”而不是“may”,但在这种情况下它们是同义词)。
这两个似乎在逻辑上强烈暗示每个 ANSI C 编译器都必须具有基本的常量折叠功能,但与此同时,似乎没有任何硬性禁止将常量表达式编译成计算表达式的代码在运行时(这样的实现仍然受益于常量表达式,因为编译器可以生成计算一次的代码,然后假设值不会改变,并且这样的实现可能会受到给定底层架构的限制 - 例如几个 RISC 架构必须使用两条指令来初始化某些可能的值,或者从内存位置加载它们)。
我还简要搜索了这个 C99 最终草案,但“折叠”产生了一个没有价值的结果,而“折叠”和“常量”各有一百多个匹配项,我目前无法分配时间来爬取。
动机
我编写了这些宏是为了在一些有点旋转的代码中更清晰地表达语义/意图:
#define UCHAR_LOW_N_BITS_m(n) (unsigned char )(UCHAR_MAX >> (CHAR_BIT - (n)))
#define UCHAR_NTH_BIT_m(n) (unsigned char )(1 << (n))
..wheren
始终是整数文字。我想得到安慰,听到一个令人放心的声音说“没关系,使用的每个远程重要的 C 编译器都会为你折叠这些常量”。(PS 我问了一个单独的问题,即是否UCHAR_NTH_BIT_m
应该像位从第 0 位或第 1 位开始一样,希望在正确的位置。)
是的,底部的宏可以变成单独的宏,例如#define UCHAR_1ST_BIT_m (unsigned char )1
通过#define UCHAR_3RD_BIT_m (unsigned char )4
代码或我在代码中碰巧需要的宏 - 虽然我不确定哪个更好,但这可能是一个有争议的问题,因为如果我想要要成为一名优秀的迂腐语言律师类型的 C 程序员,我不能完全避免顶级程序员(必须确保代码在那些 DSP/嵌入式和古老的大型机 C 实现上做正确的事情)。