Live data from Hacker News

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

gynvael.coldwind.pl

221–230 of 246 posts

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

#221
post #163

Earlier quoted context omitted.

It's only the order of evaluation that is undefined.

No, the behavior is undefined. That means, quoting the ISO C standard, "behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this document imposes no requirements". A conforming implementation could reject it at compile time, or generate code that traps, or generate code that set a to 137, or, in principle, generate code that reformats your hard drive. Some of these behav…

I was wrong.

I was looking at this:

https://en.cppreference.com/cpp/language/eval_order

I'm not sure where precisely this sequencing exception to the default "eval order undefined" rule is given, but after the 24(!) sequencing rules they do give this "++i + i++" as an explicit example of undefined behavior.

Interestingly that page says that since C++17 f(++i, ++i) is "unspecified" rather than "undefined", whatever that means, and presumably plus(++i, i++) would be too, which seems a bit inconsistent.

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

#222

Earlier quoted context omitted.

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 th…

The value of the variable is not hoisted by the Java compiler. (It's not that JVM, that only executes the byte code, what y doesn't have that kind of ambiguities.) The semantics of Java is not undefined on multiple assignments to the same variable in an expression, so it can't hoist something if it would change the outcome. Now, I don't actually know what the outcome is, because I don't remember whether `a += e` read…

    $ cat a.java 
    class a {
        public static void main (String[] args) {
            int a = 4;
            int b = a++ + ++a;
            System.out.println(b);
            System.out.println(a);
        }
    }

    $ javac a.java 
    $ java a
    10
    6

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

#223
post #152

I am, thankfully, out of this craziness now but it was fun solving ton of such puzzles from Yashavant Kanetkar books while preparing for campus hiring interviews back in 2000. "Test Your C Skills" in particular. Fun times. https://www.scribd.com/document/235004757/Test-Your-C-Skills...

"Test Your C Skills" is a published book by Yashavant Kanetkar, apparently published in 2005, and still available in paperback. The document you linked to appears to be a scan of a printed copy of that book, and is almost certainly in violation of copyright. The cover and the title and copyright pages are notably missing.

> apparently published in 2005

No. It was published in late 90s. As per this copy on Archive.org 1997

https://archive.org/details/testyourcskills00yash

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

#224
I was hoping this article would conclude with, “and the C language spec in K&R says THIS which is the correct answer”. Apparently not. So the appendix in K&R is ambiguous? And yet we use ++ so often! I can see people crawling the Linux source tree using LLM-bots looking for bad uses of ++ …

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

#225
post #190

Earlier quoted context omitted.

> The other half is "but I do know the answer Except you don't! If you claim to know the answer you've made a grave mistake and fooled yourself. If you ran the code in a compiler and used that to conclude "this is the answer" rather than "this is an answer" then now is a great time to learn how easy it is to fool yourself. You just need you ask yourself what assumptions you made. I'll wager you assumed all compilers…

> I'll wager you assumed all compilers process this line in the same way You would lose that wager. What I mean by "I do know the answer" is that I know that this is undefined behavior and why it is undefined behavior and that different compilers can give different results and also that even if I test the compiler I use to see what it does I can't count on that not changing any time the compiler gets updated.

Fair, but that was not clear to me that that's what you meant. It's clear that others interpreted it the way you intended too (since there are multiple replies saying exactly what you said) but I also don't think I'm the only one who misinterpreted. Sorry that I did.

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

#226

Earlier quoted context omitted.

I agree what you say seems reasonable at a glance. But (IIUC) the issue is that for optimization we want the compiler to assume that UB doesn't happen in order to constrain the possible code paths. So if it goes some distance down a possible execution branch and discovers UB it can trim the subtree. At that point "anything can happen" becomes an (approximate) reality. The obvious counterpoint in this particular insta…

As I understand it UB was not really intended to be for optimisation. It was so that C could compile on wildly different architectures that existed at the time. Today we don't have nearly the variety of architectures, so they in theory C doesn't need nearly as much UB (like more modern languages). Although there is one modern case where C's "anything goes" attitude has actually helped: CHERI works pretty well with C/…

is the fact that CHERI works better with C/C++ because of C/C++'s "anything goes" attitude, or simply that any hardware design that didn't support C/C++ well was discarded?

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

#227

Earlier quoted context omitted.

The compiler does comply to the spec. It's the program that fails to comply with the spec. It's definitely possible to write programs that have no undefined behavior.

The compiler is supposed to compile programs that comply with the spec, and not compile programs that don't. The concept of "compiling a program that doesn't comply with the spec" doesn't even exist! A text file that doesn't comply with the C spec isn't a C program. That's what it means to be "the spec".

That may be how you want C to be specified, but that's not how C is specified. The compiler is always allowed to assume that the input program is free of undefined behaviors.

C++ has an even more trivial example: To be a valid C++ program, all loops without side-effects must terminate. Thus determining if some C++ programs are valid would require solving the halting problem.

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

#229

Earlier quoted context omitted.

>A single `i++` or `++i`/`i += 1` is safe and useful Sure, and you don't need the assignment to be an expression with a value for it to be useful. >target[i++] = source1[j++] + source2[k++]; That's idiomatic That's idiomatic to C for sure. Also idiomatically horrible. Why are you using three index variables here? >You can write it longer, but not more clearly. target[i] = source1[i] + source2[i]; i++; This is absolut…

> Why are you using three index variables here? > You can't forget to increase one if the indices when all three are meant to go in lockstep. Obviously they are not in this example. The next line might contain: i++; j *= 42; k = srandom (k), random ();

>Obviously they are not in this example

...of utter insanity which doesn't belong in any real world code.

It just keeps getting worse, and shows why it was a horrible idea to allow this in the first place.

>The next line might contain:

    i++; j *= 42; k = srandom (k), random ();
Then that's where you do the arithmetic.

You're already doing it there, why do you need to do an assignment inside the brackets?

(This was a rhetorical question. You don't).

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

#230

Earlier quoted context omitted.

> Why are you using three index variables here? > You can't forget to increase one if the indices when all three are meant to go in lockstep. Obviously they are not in this example. The next line might contain: i++; j *= 42; k = srandom (k), random ();

>Obviously they are not in this example ...of utter insanity which doesn't belong in any real world code. It just keeps getting worse, and shows why it was a horrible idea to allow this in the first place. >The next line might contain: i++; j *= 42; k = srandom (k), random (); Then that's where you do the arithmetic. You're already doing it there, why do you need to do an assignment inside the brackets? (This was a r…

If you only have a single index, that you continue to increment, you don't need an index at all, you just invoke memcpy.

It is useful to distinguish between consuming an element and only jumping to it. So you would have an ptr[i++] for consuming the current token, but not, when you are switching to another token.

A grouping of index and array modification also provides clarity about the intention. It would read very annoying if that constantly would be split into two steps, and also provides more room for error.

It's obvious that you do prefer the stylistic choices Go made, but that doesn't mean everyone does.

Post reply on HN