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

在变量和指针中工作的多个“++”

c
  •  1
  • Rhee  · 技术社区  · 16 年前

    这就是我认为的 ++ 运算符

    1. a++; // a+=1 after calculating this line
    2. ++a; // a+=1 before calcuating this line

    我正在努力学习指针,我想我误解了一些东西。

    int a=10;
    int arr[3]={0,1,2};
    int *ptr;
    ptr=arr;
    
    printf("%d,%d,%d,%d\n",a++,a++,++a,++a);
    printf("%d,%d,%d\n", ptr[0],ptr[1],ptr[2]);
    printf("%d,%d,%d,%d,%d,%d", * ptr++, ( * ptr)++, ++ * ptr, ++( * ptr), *++ptr, * ptr);
    

    我期望输出为:

    12, 12, 12, 12
    0,1,2
    3,3,3,3,3,3,3
    

    但事实并非如此,而是这样:

    13,12,14,14
    0,1,2
    4,3,2,2,2,2
    

    为什么会这样?

    4 回复  |  直到 16 年前
        1
  •  6
  •   int3    16 年前

    您不应该对一个函数做多个参数增量。因为它们的计算顺序不明确。这种代码的结果是未定义的。

    含义: printf("%d,%d,%d,%d\n",a++,a++,++a,++a); 应该写为

    a++; a++;
    ++a; ++a;
    printf("%d, %d, %d, %d\n", a, a, a, a);
    

    首先尝试解决这个问题,看看结果是否仍然令人困惑。

    更一般地说,在一对 sequence points.

    编辑: 克里斯是对的,在任何地方写四个增量都没有意义。更好地回答你的问题:一个函数 void f(int) void g(int) int a=0 ,

    f(++a) = f(1);
    f(a++) = f(0);
    g(++a, ++a) = g(???); // undefined!
    

    所以,函数的参数最多增加一次。

        2
  •  6
  •   James McNellis    16 年前

    不要这样做。行为未定义。

    根据C规范(第6.5节)

    在上一个和下一个之间 对象应具有的序列点 其存储值最多修改一次 通过表达式的计算。 此外,优先值应为 仅用于确定值 存储。

    除非句法说明 或以后另行规定(用于 函数调用运算符(),&, 是吗?:,和逗号运算符)。 子表达式的计算顺序 副作用的顺序 两种情况均未说明。

    换言之,如果在函数的参数中多次更新变量的值,则不会编写合法的C代码。

        3
  •  3
  •   Sinan Ünür    16 年前

    参见C常见问题解答中的3.2:

    3.2:在我的编译器下,代码

        int i = 7;
        printf("%d\n", i++ * i++);
    

    打印49。不管评估的顺序如何,不是吗 打印56?

    A:尽管postIncrement和postDecrement运算符是-- 在得到前一个值后执行操作, “after”的含义经常被误解。它是 保证执行增量或减量 放弃前一个值后,在任何 计算表达式的其他部分。仅仅是 保证更新将在 表达式被视为“完成”(在下一个“序列”之前 要点,“在ANSI C的术语中;见问题3.8)。在 例如,编译器选择将前一个值乘以 以及稍后执行这两个增量。

    包含多个不明确方面的代码行为 效果始终未定义。(不严格地说, “多重的,模棱两可的副作用”,我们指的是 单个中的递增、递减和赋值运算符 导致同一对象被修改的表达式 两次或修改后检查。这是粗糙的 定义;请参见问题3.8了解精确的定义,以及问题 11.33对于“未定义”的含义,不要试图寻找 你的编译器是如何实现这些东西的(与 许多C教科书中不明智的练习);K&R明智地指出 出去,“如果你不知道 怎样 它们是在各种机器上完成的, 这样的纯真可能有助于保护你。”

    参考文献:K&R1秒。2.12 p.50;k&r2秒2.12第54页;国际标准化组织 秒。6.3;H&S秒7.12第227-9页;CT&P第3.7秒47;个人电脑 秒。9.5 pp.1-1。

        4
  •  2
  •   Heath Hunnicutt    16 年前

    它不是“每行”,而是“每序列点”,类似于“每表达式”,似乎是由前增量和后增量产生的结果。

    实际上,增量总是立即发生。唯一的变化是术语值是否会导致初始值或后续值。

    要完全理解C不是面向行的,请参考标准并阅读有关“顺序点”的部分。

    以“”开头的行是预处理器输入。C的预处理器是面向行的,但是,否则,C本身认为换行符与任何其他空白字符(如制表符或空格)相同。