操作员间接禁止(或不?)定义整数常量表达式(在C中)

时间:2014-02-24 18:28:58

标签: c syntax c99 language-lawyer

在标准C(C99 / C11)中,我们有所谓的整数常量表达式,它们是常量表达式,其操作数都是常量整数。

以下定义适用:

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

  

整数常量表达式)应具有整数类型且必须   只有整数常量,枚举常量的操作数,   字符常量,sizeof表达式,其结果是整数   常量和浮动常量,它们是直接操作数   管型。

Standard C99

在更一般的常量表达式的定义之后出现 (由于整数常量表达式是在常量表达式之后定义的,我假设前者是最后一个的特殊情况。)

另一方面,条件表达式被视为常量表达式,受以下规则约束:

标准C99,第6.6节:

  

常量表达式不应包含赋值,增量,   递减,函数调用或逗号运算符,除非它们是   包含在未评估的子表达式中。

通过展开条件表达式的含义,我们可以归结为后缀表达式和/或一元表达式

现在,如果我们将这些约束应用于整数常量表达式,我们粗略地得出它们由条件表达式组成,这些条件表达式的限制使得每个操作数都是整数/枚举/字符常量(或浮点常量)紧跟在演员之后,并且没有赋值,递增,递减,函数调用或逗号运算符

  • 简单来说,我们假设 E 是一个这样的表达式,没有任何sizeof运算符且没有未计算的操作数。

我的问题是:
以下操作符是否在 E

中间接禁止
  • &(地址),
  • *(间接),
  • [](array-subscript),
  • .(struct member),
  • ->(指向结构成员的指针)。

另外,复合文字是否也被禁止?

备注:我有兴趣回答严格符合程序的问题(C99 / C11)。

我认为它们不能处于 E 的任何子表达式中,但我不确定这是否完全正确。我的快速推理如下:

  • 如果 F E 的整数常量子表达式,则 F 根据定义具有整数类型T
  • 如果一元运算符&出现在 F 之前 E ,那么& F 就会出现一个类型为“指针”的操作数到T“, E 中不允许(尽管 F 不是对象,但只是整数值,因此无法应用& )。因此&不能出现在任何 E 中。
  • 由于 F 没有任何指针类型,因此表达式*F无意义。
  • 下标运算符[]用于表示数组内的元素。这意味着我们会在 E 中拥有A[N]之类的东西。这里,N必须是整数常量表达式。但是我们注意到A也是一个操作数,但它是array类型的对象, E 中不允许这样做。这意味着数组下标运算符不能出现在 E
  • 如果我们在 E 中有运算符.->,则表示它们在 E 中使用,如下所示:{{1} }。因此,我们有操作数S.memb pS->memb,其类型为SstructunionpS。但 E 中不允许使用这些“操作数”。
  • E 中不允许使用复合文字,因为它们是左值,这意味着它们在程序运行时会有一个地址。由于编译器无法知道这样的地址,因此涉及复合文字的表达式不被视为常量。

你认为我的推理是对的吗? 您是否知道特殊情况,其中一些运算符或表达式可以是整数常量表达式的一部分(如我所指示的 E 的限制情况)。

1 个答案:

答案 0 :(得分:2)

ICE只需要将值(行话中的rvalues)作为构成它的主表达式,而不是对象(左值)。

如果你从那里建立以排除运营商,你会看到

  • 不能使用左值作为操作数的运算符(赋值,递增,递减,一元&

  • 任何产生左值的运算符都不能使用(一元*,数组成员[],成员->

  • 需要.作为参数的struct运算符,因为

    • struct

    • 没有文字
    • 复合文字是用词不当,它们是对象。

    • 也不允许进行函数调用。

其中一些运算符可以在未评估(或不应该)的位置出现,特别是_Alignof,宏offsetof和某些sizeof的出现。