【发布时间】:2016-04-08 16:30:25
【问题描述】:
问题
我很好奇是否可以保证在 C 中进行常量折叠。
我看过的地方
This link 在我不知道其声誉的网站上发表了一条不经意的评论:
所有 C 编译器都可以折叠在宏扩展后出现的整数常量表达式(ANSI C 要求)。
但我没有看到任何东西,例如C 编程语言,第二版(我认为已经彻底更新以说明 ANSI C 的所有细节)。但是在检查索引以获取相关单词的引用后,我没有发现任何可以保证这一点的东西。尤其是第 38 页和第 209 页非常接近,因为他们说任何 可以在编译时计算 的表达式都可以在可以使用常量的地方使用(如果我们足够迂腐的话,可能会有一些限制) ,并且它说这样的表达式“可能”在编译时被评估,而不是“will”/(一些同义词)。
我搜索了this C89 final draft。单词“folding”和“folded”没有产生值的结果,搜索“constant expression”产生了63个匹配,其中我检查了大约一半。感兴趣的主要部分似乎与本书基本相同(它使用“can”而不是“may”,但在这种情况下这些是同义词)。
这两个似乎在逻辑上强烈暗示每个 ANSI C 编译器都必须具有基本的常量折叠功能,但与此同时,似乎没有任何硬性禁止将常量表达式编译成代码在运行时计算表达式(这样的实现仍然受益于常量表达式,因为编译器可以生成计算一次然后假设值不会改变的代码,并且这样的实现可能会受到给定底层架构的限制 - 例如一些 RISC 架构必须使用两条指令来初始化某些可能的值,或者从内存位置加载它们。
我还简单地搜索了this C99 final draft,但“折叠”产生了一个没有价值的结果,而“折叠”和“常量”各有一百多个匹配项,我目前无法分配时间来抓取。
动机
我编写这些宏是为了在一些位旋转的代码中更清晰地表达语义/意图:
#define UCHAR_LOW_N_BITS_m(n) (unsigned char )(UCHAR_MAX >> (CHAR_BIT - (n)))
#define UCHAR_NTH_BIT_m(n) (unsigned char )(1 << (n))
..其中n 始终是整数文字。我想得到安慰,听到一个令人放心的声音说“没关系,使用的每个远程重要的 C 编译器都会为你折叠这些常量”。 (P.S. 我问了一个单独的问题,关于 UCHAR_NTH_BIT_m 是否应该像 bits start from the 0th or 1st bit 一样行事,希望在正确的地方。)
是的,底部的可以变成单独的宏,例如#define UCHAR_1ST_BIT_m (unsigned char )1 到 #define UCHAR_3RD_BIT_m (unsigned char )4 或者我碰巧在代码中需要的许多代码 - 虽然我不确定其中哪个更好,但这可能是一个有争议的问题,因为如果我想成为一个好的迂腐语言 -律师类型的 C 程序员,我无法完全避免排名靠前的程序员(必须确保代码在那些 DSP/嵌入式和古老的大型机 C 实现上做正确的事情)。
【问题讨论】:
-
这取决于编译器开发人员。 “Can”是美国的“may”,意思是你被允许但你不必这样做。是的,任何好的编译器都可以做到。
-
我不认为“can”的用法仅限于美式英语。
-
@KlasLindbäck:我感谢您的澄清,但我知道:这就是为什么我说“似乎基本相同” - 因为我明白虽然有措辞不同,但它的意思基本相同事物。我会编辑它以减少进一步误解的机会。
-
那么,您使用全大写符号(C 中明确表示这是宏或预处理器符号),加上小写的
_m后缀表示该符号是宏?好的。 -
“C 编程语言,第二版(我认为它已经彻底更新以考虑 ANSI C 的所有细节)”不是。与 C90 兼容的第二次更新是半心半意的。当然,C90 标准已经过时了。
标签: c language-lawyer constant-expression constantfolding