关于强制转换整数常量表达式(在标准C中)

关于强制转换整数常量表达式(在标准C中),c,syntax,c99,language-lawyer,C,Syntax,C99,Language Lawyer,在标准C(我指的是C99或C11)中,我们有所谓的整数常量表达式,这些常量表达式的操作数都是常量整数。还有其他限制,以避免表达式中的逗号运算符 但是,在某些特殊情况下,允许使用其他非整数对象(甚至非常量)。 例如,如果将sizeof运算符应用于在转换时大小已知的对象,则允许将其作为整型常量表达式的一部分(请注意sizeof始终返回整数值) 此外,有时也允许显式转换为整数类型。 标准C99确立了以下规则: 标准C99第6.6节(第6段): 整数常量表达式)应为整数类型,且 仅具有整数余项、枚举常量

在标准C(我指的是C99或C11)中,我们有所谓的整数常量表达式,这些常量表达式的操作数都是常量整数。还有其他限制,以避免表达式中的逗号运算符

但是,在某些特殊情况下,允许使用其他非整数对象(甚至非常量)。
例如,如果将
sizeof
运算符应用于在转换时大小已知的对象,则允许将其作为整型常量表达式的一部分(请注意
sizeof
始终返回整数值)

此外,有时也允许显式转换为整数类型。
标准C99确立了以下规则:

标准C99第6.6节(第6段):

整数常量表达式)应为整数类型,且 仅具有整数余项、枚举常量、, 字符常量,sizeof表达式,其结果为整数 常量和作为的直接操作数的浮点常量 演员

我的问题是:作为强制转换的直接操作数的浮点常量的确切含义是什么

浮动常数类似于3.14e+3或井0x2.11p-5。
也就是说,不是浮点类型的通用常量表达式,而只是浮点文本。
那么,我理解,在上述定义中,只有这样的东西是允许的:

 (int) 3.14
但不允许涉及浮动文本的操作。
这排除了以下情况:

 (int) -3.14  /* The minus sign is not part of the constant: it is an operator */
 (int) (3.14) /* The parenthesis are an operator acting on the literal 3.14 */
 #define BITW (int) (3.14)
 struct { unsigned bitfield: BITW } test;  // Translation success
最后一种情况不需要在翻译时执行任何浮点算术运算,它相当于在没有括号的情况下执行相同的运算:
(int)3.14

但是,它不是强制转换的立即操作数

< > >强> >我们必须考虑<代码>(int)(3.14)< /代码>是[强>整数常量表达式<强> >的一部分(根据定义)?p> 另一方面,编译器GCC(带有选项:-std=c99-pedantic errors)告诉我
(int)(3.14)
是一个有效的整型常量表达式,例如在如下声明中:

 (int) -3.14  /* The minus sign is not part of the constant: it is an operator */
 (int) (3.14) /* The parenthesis are an operator acting on the literal 3.14 */
 #define BITW (int) (3.14)
 struct { unsigned bitfield: BITW } test;  // Translation success

(但是,通过执行
#定义BITW(int)(+3.14)
无法按预期进行翻译)

虽然措词选择不当可能意味着
(int)(3.14)
不符合整数常量表达式的条件,但我认为这只是措词中的一个缺陷。有一个类似的问题可以说是
NULL
规范的一个bug:它可以是任何空指针常量,其中空指针常量定义为:

  • 值为0的整数常量表达式,或
  • 这样的表达式转换为
    void*
  • 但是,为了用作
    NULL
    的定义,表达式应正确插入括号;我所知道的所有现有实现都是这样做的。但严格来说,
    (void*)0
    是空指针常量,
    ((void*)0
    不是空指针常量(它是圆括号运算符对空指针常量的应用)


    理想情况下,应该在规范中的某个地方添加语言,以澄清括号不会影响此类内容。

    有关信息,gcc维护人员和开发人员Joseph Myers在其个人页面上讨论了C99标准中常量表达式的问题。原始文本10年前出现在comp.std.c上,但后来被扩展

    在他不断提出的问题中,你所描述的问题在他的观点(5)中进行了讨论:

    (5) 常数的“操作数”(6.6第6段和第8段)是什么 表情?在某些情况下,它可能意味着“最终”操作数 将各种运算符向下递归到其操作数,但 未指定。可能是复合文字,例如(const int){0} 不是指常量表达式(作为对 匿名变量),但从文本中很难清楚0 这里不是操作数。当复合文字出现在sizeof中时 其结果不是未赋值中的整数常量的表达式 表达式的部分,表达式是否为算术常数 表达式可能取决于化合物中存在的类型转换 文字。此外,人们会认为括号的意思是 纯语法而不是有“操作数”,因此(int)(0.0)是 整数常量表达式,与(int)0.0和((void*)0)相同 一个空指针常量,但没有说明

    他在提及本案文时写道:

    我还讨论了有关常量表达式的问题(不是以上述预DRs的形式;在实现经验之后,部分可能成为DRs)


    据我所知,第(5)点提出的术语问题在DR.中没有进一步提出。

    只是关于
    sizeof
    的注释,它是一个仅编译时的运算符,因此它始终是一个“整数常量表达式”。我不认为有任何类型的大小不能是整数。@JoachimPileborg:那不是真的。看,例如@ruakh总是那些该死的vla,总是忘记它们。我最近一直在做很多C++的工作。约阿希姆·皮莱堡:这不是真的。C99中有VLA类型,它们不能在整数常量表达式中与
    sizeof
    一起出现。也就是说,公平地说,在编译时获取大小已知的对象的
    sizeof
    肯定不是“非常量”。我觉得C99
    6.5.1 p5
    涵盖了这一点。@ShafikYaghmour:我不同意,因为6.6p6说:“浮动常量”,6.5.1定义“主要表达式”,6.4.4定义“浮动常量”为浮动“文字”。就像@hvd说的,它们当然有相同的含义