c - 在定义整数常量表达式时间接禁止(或不禁止?)运算符(在 C 中)

标签 c syntax c99 language-lawyer

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

以下定义适用:

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

An integer constant expression) shall have integer type and shall only have operands that are integer costants, enumeration constants, character constants, sizeof expressions whose results are integer constants, and floating constants that are the immediate operands of casts.



Standard C99

这出现在更通用的定义之后 常量表达式 .
(由于 整数常量表达式 是在 常量表达式 之后定义的,我假设前者是最后一个的特例。)

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

标准 C99,第 6.6 节:

Constant expressions shall not contain assignment, increment, decrement, function-call, or comma operators, except when they are contained within a subexpression that is not evaluated.



通过展开的含义条件表达式 我们可以下降到后缀表达式 和/或 一元表达式 .

现在,如果我们将这些约束应用于 整数常量表达式 ,我们粗略地得到它们由条件表达式组成,以这样一种方式限制每个操作数都是整数/枚举/字符常量(或紧跟在强制转换之前的浮点常量),并且这样 没有赋值、递增、递减、函数调用或逗号运算符 .
  • 为简单起见,让我们假设 E 是这样的表达式,没有任何 sizeof运算符并且没有未计算的操作数。

  • 我的问题是:
    中是否间接禁止了以下操作符? E :
  • & (地址),
  • * (间接),
  • [] (数组下标),
  • . (结构成员),
  • -> (指向结构成员的指针)。

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

    附加说明:我有兴趣回答严格符合程序 (C99/C11) 的这个问题。

    我认为它们不能出现在 的任何子表达式中E ,但我不确定这是否完全正确。我的快速推理如下:
  • 传真 的整数常量子表达式E ,然后 传真 根据定义,具有整数类型 T .
  • 如果一元运算符 &出现在 之前传真 E ,然后 &F in 类型为“指向 T 的指针”的操作数,这在 中是不允许的E (尽管 F 不是一个对象,而只是一个整数值,所以 & 不能应用)。因此&不能出现在任何 E .
  • 传真 没有任何指针类型,它没有意义表达式*F .
  • 下标运算符 []用于指示数组内的元素。这意味着我们将在 E 类似 A[N] .在这里,N必须是整数常量表达式。但是我们注意到 A也是一个操作数,但它是类型 array 的对象,这在 中是不允许的E .这意味着数组下标运算符不能出现在 中。 E .
  • 如果我们在 E 运营商.-> ,这意味着它们在 中使用E 如下:S.memb pS->memb .因此,我们有操作数 S其类型为 structunionpS这是一个 pointer to struct or pointer to union .但是这些类型的“操作数”在 中是不允许的。 E .
  • 中不允许使用复合文字E ,因为它们是左值,这意味着它们在程序运行时会有一个地址。由于编译器无法知道这样的地址,因此不会将涉及复合文字的表达式视为常量。

  • 你觉得我的推理对吗?
    您是否知道一些特殊情况,其中一些运算符或表达式可以是 的 [一部分]整数常量表达式 (如在我表示的受限情况下 E )。

    最佳答案

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

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

  • 不能使用任何需要左值作为操作数的运算符(赋值、递增、递减、一元 &)
  • 任何产生左值的运算符都不能使用(一元 * ,数组成员 [] ,成员 -> )
  • .需要 struct 的运营商作为论证,因为
  • struct 没有文字
  • 复合文字是用词不当,它们是对象。
  • 函数调用也是不允许的。

  • 其中一些运算符可能会出现在未评估(或不应该评估)的地方,特别是 _Alignof ,宏offsetof以及sizeof的一些出场.

    关于c - 在定义整数常量表达式时间接禁止(或不禁止?)运算符(在 C 中),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21995965/

    相关文章:

    c - 如何检查内存区域是否映射到文件?

    c - 我的 pid 标识符不是预期的

    c++ - C++11 中的 (Di|Tri) 图

    c - 声明复杂 C 结构化常量数据的策略?

    c - 将字符包读入数组,然后解析

    c - 我正在尝试制作二维数组,将其传递给函数,然后在 main 中更新修改后的数组

    java - 没有大括号的嵌套 if-else 行为

    MySQL 语法 - 变量的标准偏差,而不是列

    sql - INNER Join 的案例声明

    C99 分段溢出 strlen,不一致