Live data from Hacker News

Int a = 5; a = a++ + ++a; a =? (2011)

gynvael.coldwind.pl

111–120 of 246 posts

Re: Int a = 5; a = a++ + ++a; a =? (2011)

#111

Earlier quoted context omitted.

I don’t work a ton with C, but I wonder how C programmers keep track of what behavior is and is not defined. It seems like there are many possible edge cases.

They don't really. In fact there are many things that are technically UB but are so common that compilers can't really treat them as UB. E.g. type punning via unions.

Type punning via unions is not UB in C in general, but it is in C++ IIRC.

I write "in general" because, as with other forms of memory reinterpretation (memcpy or copy through a character type), evaluating a trap representation triggers UB.

Re: Int a = 5; a = a++ + ++a; a =? (2011)

#112

Earlier quoted context omitted.

It's Undefined Behavior. So you can instrument all you want, the answer will still be wrong. You'll capture what your particular compiler does under some particular conditions (opt flags, surrounding code, etc.) but that will not be representative of what can happen in the general case (hint : anything can happen with UB).

It doesn't matter if the answer is wrong. You run the test program and then replace the code by the answer. This basically weeds out the UB.

But since it is a UB, there's no guarantee that your test program produces the same result as the same code running on production, even if you have the same compiler.

Re: Int a = 5; a = a++ + ++a; a =? (2011)

#113

Earlier quoted context omitted.

> It's Undefined Behavior. Susam's post doesn't make this clear. The quotes from K&R say that the modifications to the variable may take place in any order, but they don't directly say that doing this is Undefined Behavior, which would make it permissible to do anything, including e.g. interpreting the increments as decrements. The C99 standard is quoted saying this: >> Between the previous and next sequence point an…

Compilers are not able to prevent you from violating must/shall in the general case. So they're not held to that bar. Unless the standard says not to compile it, it's not a compiler bug. Also, imagine a situation where the line of code actually lists three different variables, but all three of them are passed in by address. It quickly becomes impossible for the compiler to know you violated the spec by reusing the sa…

> Also, imagine a situation where the line of code actually lists three different variables, but all three of them are passed in by address. It quickly becomes impossible for the compiler to know you violated the spec by reusing the same variable.

OK. What is the value of a spec to which compliance is impossible?

Re: Int a = 5; a = a++ + ++a; a =? (2011)

#115
post #95

Earlier quoted context omitted.

It's defined. And called "operator precedence", both post/pre-increment have a higher precedence than the single "+". At least according to this: https://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Exp... I think the main confusion here comes from the fact that "a" is just a value, not a pointer, where it matters when the value/address which the pointer points at is accessed (before of after the increment of the…

Nope. Order of evaluation and operator precedence are completely unrelated. They should have been defined to be the same, but instead order of evaluation was left undefined. So if you write ++a + a++, operator precedence means this will be interpreted as (++a) + (a++), not say ++(a + a)++, but it is up to the compiler whether to execute ++a or a++ first, rather than executing them left to right.

Sometimes it helps to test. Which I just did. :-)

Actually the compiler (at least clang) warns about this:

    $ gcc -W -Wall test.c -o test
    test.c:8:7: warning: multiple unsequenced modifications to 'a' [-Wunsequenced]
            a = a++ + ++a;
                 ^    ~~
    1 warning generated.
The undefined behaviour stems from the fact that "a" is modified multiple times between the "sequence points" (so it's irrelevant to the actual problem that this happens with ++, --, pre-, or, post-, or in which order) We only can modify the variable safely once on the right side without entering bizarro world.

A construct like this certainly can be confusing.

Re: Int a = 5; a = a++ + ++a; a =? (2011)

#116

Earlier quoted context omitted.

I don’t work a ton with C, but I wonder how C programmers keep track of what behavior is and is not defined. It seems like there are many possible edge cases.

We get by on a combination of matching patterns (any pointer cast gets a lot of scrutiny, for example), compiler warnings, tools like UBSan, debugging when things go wrong, and sheer dumb luck. Having an understanding of how the code gets transformed into machine code helps. For this case, there's the basic idea that `a++` will boil down to three basic conceptual operations: fetch, add, and store, and those can be po…

> Having an understanding of how the code gets transformed into machine code helps

I'm not sure about that. Knowing assembly is not a substitute for knowing how the language is defined. Sometimes C/C++ programmers with some assembly knowledge reason themselves into thinking that what they're asking of the language must have well-defined behaviour, when in fact it's undefined behaviour. It doesn't really matter whether interleaving order can change the output. (++i)++ is, apparently [0], undefined behaviour in C but has well defined behaviour in C++.

[0] https://stackoverflow.com/a/58841107

Re: Int a = 5; a = a++ + ++a; a =? (2011)

#117
post #5

The code in the post seems very similar to the one in my own post from 2010: https://susam.net/sequence-points.html int a = 5; a += a++ + a++; I do remember that this particular code snippet (with a = 5, even) used to be popular as an interview question. I found such questions quite annoying because most interviewers who posed them seemed to believe that whatever output they saw with their compiler version was the co…

Well... tried it on macOS using vanilla gcc, the results surprised me:

  $ /bin/cat x.c; gcc -w -o x x.c; ./x
  #include 
  
  int main()
  {
      int a = 5;
      a += a++ + a++;
      printf("a = %d\n", a);
  }
  a = 18
Not what I expected. This must be how it works:

- The first a++ expression results in 5, after a = 6 - The second a++ expression results in 6, after a = 7 - Only then the LHS a is evaluated for the addition-assignment, so we get: a = 7 + 5 + 6 = 18

Re: Int a = 5; a = a++ + ++a; a =? (2011)

#118

Earlier quoted context omitted.

Genuinely curious, so this is undefined behavior and depends on the compiler. I get that. Java, and other languages, can do these same operations but their compilers produce bytecode that runs on a virtual machine (JVM) compiled to machine code just-in-time. Would this same code in Java possibly yield different results based on the platform the JVM was running on because of the platform specific JIT compiler? Maybe t…

It's been quite a while, but IIRC, in Java these statements actually do have a defined behavior. The ++x is a "pre-increment", meaning the value of the variable is incremented prior to evaluating the expression, while the "post-increment" "x++" is the other way around: the expression evaluates to x, then x is incremented afterwards. All expressions are left-to-right.

That behavior is inherited from C. The pre/post increment behavior is actually the same in every language that uses them. The priority of operation is also usually the same as well.

The reason the question is tricky is because those operators change the value of a as the full expression is progressively executed.

It's not immediately clear to me what the answer in Java would be.

Just take a++ + ++a for example:

If the value if `a` is hoisted by the jvm then it could be 5++ + ++5, so 5 + 6.

But if it's executed left to right and `a` is looked up every time, then it becomes 5++ + ++6, so 5 + 7.

Re: Int a = 5; a = a++ + ++a; a =? (2011)

#119
post #69

Earlier quoted context omitted.

Awk also says it's 12. awk 'BEGIN{a=5; a = a++ + ++a; print a}' 12

https://www.gnu.org/software/gawk/manual/gawk.html#index-pre... "When side effects happen is implementation-defined. In other words, it is up to the particular version of awk."

Android appears to use the One True AWK.

  :/ $ awk 'BEGIN{a=5; a = a++ + ++a; print a}'
  12

  :/ $ which awk
  /system/bin/awk

  :/ $ awk --version
  awk version 20240728

Re: Int a = 5; a = a++ + ++a; a =? (2011)

#120
post #5

The code in the post seems very similar to the one in my own post from 2010: https://susam.net/sequence-points.html int a = 5; a += a++ + a++; I do remember that this particular code snippet (with a = 5, even) used to be popular as an interview question. I found such questions quite annoying because most interviewers who posed them seemed to believe that whatever output they saw with their compiler version was the co…

Genuinely curious, so this is undefined behavior and depends on the compiler. I get that. Java, and other languages, can do these same operations but their compilers produce bytecode that runs on a virtual machine (JVM) compiled to machine code just-in-time. Would this same code in Java possibly yield different results based on the platform the JVM was running on because of the platform specific JIT compiler? Maybe t…

I'd be badly surprised if the jvm jit went through C, so if this monstrosity is well defined in Java it's well defined once well defined everywhere.

but still, if it were, it was and remained, as gp points out, bad practice...

Post reply on HN