提问人:pmor 提问时间:2/1/2022 更新时间:2/1/2022 访问量:59
条件包含:字符常量的数值:在 #if/#elif 与不在 #if/#elif 范围内:为什么匹配是实现定义的?
Conditional inclusion: numeric value for the character constants: within #if/#elif vs. without #if/#elif: why matching is implementation-defined?
问:
案例 A:C11,6.6 常量表达式,语义,5:
如果在翻译环境中计算浮动表达式,则算术范围和精度应至少与在执行中计算表达式一样大 环境。116)
这需要以下程序返回 0:
#include <float.h>
#define EXPR DBL_MIN * DBL_MAX
double d1 = EXPR;
double d2;
#pragma STDC FENV_ACCESS ON
int main(void)
{
d2 = EXPR;
return d1 == d2 ? 0 : 1;
}
案例 B:C11,6.10.1 条件包含,语义,4:
这些字符常量的数值是否与表达式中出现相同字符常量时获得的值匹配(而不是在 #if 或 #elif 指令中)由实现定义。168)
它不需要以下程序返回 0:
#define EXPR 'z' - 'a' == 25
int main(void)
{
_Bool b1 = 0;
_Bool b2;
#if EXPR
b1 = 1;
#endif
b2 = EXPR;
return b1 == b2 ? 0 : 1;
}
问题:使“案例 B”实现定义行为的基本原理是什么?
答:
C11标准(我将引用本文档草案)定义了两个字符集:
5.2.1 字符集
1 应定义两组字符及其相关的排序顺序: 写入源文件的集合(源字符集), 以及在执行环境中解释的集合(执行字符集)。每个集合进一步分为一个基本字符集,其内容由该子句给出,以及一组零或 更多特定于区域设置的成员(不是 BASIC 的成员 字符集)称为扩展字符。组合套装也是 称为扩展字符集。成员的值 执行字符集是实现定义的。
此外,不要求这些集中的等效字符由相同的值表示,也不要求按顺序存储拉丁字母。因此,在给出的示例中,这两个集合中的 need 的值并不相同。'z' - 'a'
现在,转换阶段的顺序指定使用源字符集执行宏调用和计算(以及其他预处理指令),但在转换为执行字符集后计算可执行代码中出现的表达式:
5.1.1.2 转换阶段
...
4. 执行预处理指令,扩展宏调用,并_Pragma
一元运算符表达式 执行。如果字符序列与 通用字符名称由令牌串联生成 (6.10.3.3),则行为未定义。#include
预处理 指令导致从 第 1 阶段到第 4 阶段,递归。所有预处理指令都是 然后删除。
5. 字符常量和字符串文字中的每个源字符集成员和转义序列都转换为相应的成员 执行字符集的执行字符集;如果没有相应的成员, 它被转换为实现定义的成员,而不是 null(宽)字符。
。
因此,由于这些字符集之间的关系是实现定义的,并且由于基于字符的常量表达式的两次出现被定义为使用不同的集,因此它们可能具有不同的计算这一事实也必须由实现定义。
评论