代码之家  ›  专栏  ›  技术社区  ›  PJT

C中的运算符关联性,特别是前缀和后缀的增减量

  •  4
  • PJT  · 技术社区  · 15 年前

    在C操作中,关联性是指增量、减量和赋值。

      2. postfix ++ and -- 
      3. prefix ++ and -- 
      16. Direct assignment = 
    

    完整的列表在这里找到 Wikipedia Operators in C

    我的问题是什么时候

    int a, b;
    
    b = 1;
    a = b++;
    
    printf("%d", a); // a is equal to 1
    
    b = 1;
    a = ++b;
    
    printf("%d", a); //a is equal to 2
    

    当后缀增量运算符应该在直接赋值之前发生时,为什么用B++将a等于1?

    为什么前缀增量运算符和后缀在赋值之前都不同?

    我很肯定我不明白,当涉及到操作关联性时,一些非常重要的东西。

    3 回复  |  直到 15 年前
        1
  •  15
  •   kennytm    15 年前

    后缀运算符 a++ 将递增 a 然后返回原始值,即类似于:

    { temp=a; a=a+1; return temp; }
    

    以及前缀 ++a 将返回新值,即

    { a=a+1; return a; }
    

    这与操作员无关 优先 .

    (关联性决定了 a-b-c 等于 (a-b)-c a-(b-c) )

        2
  •  5
  •   AnT stands with Russia    15 年前

    运算符优先级和关联性并不能告诉您发生了什么 之前 然后发生了什么 之后 . 运算符优先级/关联性与此无关。在C语言中,时间关系如“before”或“after”由所谓的 序列点 只有 按顺序点(这是完全独立的故事)。

    运算符优先级/关联性只告诉您哪些操作数属于哪些运算符。例如,表达式 a = b++ 可以正式解释为 (a = b)++ 作为 a = (b++) . 运算符优先级/关联性在这种情况下,只告诉您后一种解释是正确的,前一种解释是错误的(即 ++ 适用于 b 而不是结果 a = b )

    再一次,这并不意味着 应该先递增。运算符优先级/关联性,再一次,与“第一”和“下一个”发生的事情无关。它只是告诉你 b++ 表达式被分配给 a . 根据定义,结果 B+ (后缀增量)是 起初的 价值 . 这就是为什么 会得到 起初的 价值 ,即1。当变量 将得到递增是完全无关的,只要 得到分配 起初的 值。编译器可以以任意顺序和增量计算此表达式。 任何时候:任何事情都会发生,只要 不知怎的得到了 起初的 价值 (没有人真正关心“不知何故”在内部是如何工作的)。

    例如,编译器可以计算 A=B++ 作为下列基本操作顺序

    (1) a := b
    (2) b := b + 1
    

    或者它可以评估如下

    (1) b := b + 1
    (2) a = b - 1
    

    注意在第一种情况下 实际上在结尾处递增,而在第二种情况下 首先递增。但在这两种情况下 获取相同的正确值-的原始值 这就是它应该得到的。

    但我必须重申,以上两个例子仅用于说明目的。实际上,表达方式 a = ++b A=B++ 内部没有序列点,这意味着从您的角度来看,这些表达式中的所有内容都会发生 同时 . 没有“before”、“after”、“first”、“next”或“last”。在某种意义上,这些表达式是“原子的”,不能有意义地分解成一系列更小的步骤。

        3
  •  1
  •   Jerry Coffin    15 年前

    正如Andreyt已经指出的,优先级和关联性并不能告诉你评估的顺序。他们只告诉你分组的事情。例如,优先权就是使用 a*b+c 分组为 (a*b)+c 而不是 a*(b+c) . 编译器可以自由计算 a , b c 在任何顺序上,它都认为适合这些表达式中的任何一个。当具有相同优先级的运算符(通常是相同的运算符)时,关联性告诉您有关分组的信息。例如,它告诉你 a-b-c 等于 (a-b)-c a-(b-c) (否则,减法是左相关的)。

    评估顺序由序列点定义。在完整表达式的末尾有一个序列点(除其他外)。在顺序点上,所有先前的评估都必须进行,并且任何后续的评估都不能进行。

    查看您的具体示例,在 a=b++; 结果主要来自后增量本身的定义。后增量生成变量的前一个值,在下一个序列点之前的某个时间,该变量的值将递增。预增量生成应用增量的变量值。然而,这两种情况都不意味着变量必须以相对于赋值的任何特定顺序递增。例如,在预增量示例中,编译器可以完全自由地执行以下操作:

    temp = b+1;
    a = temp;
    b = b + 1;
    

    同样,在后递增版本中,变量可以在赋值之前或之后递增:

    a = b;
    b = b + 1;
    

    或:

    temp = b;
    b = b + 1;
    a = temp;
    

    但是,无论是哪种方式,分配给 必须是的值 在它增加之前。