EmbeddedRelated.com
Memfault Beyond the Launch

(So far, 76 people got it right out of 342 for a success rate of 22%)

(Thank you to Jason Sachs for submitting this question)


What does hide_and_seek() return in this C program?

#include <stdint.h>
/* Count all the positive integers */
int32_t hide_and_seek(void) {
    int32_t sum = 0;
    for (int32_t i = 1; i >= 0; ++i)
    {
        ++sum;
    }
    return sum;
}
Pick one:
-2147483648
2147483647
it depends on sizeof(int)
this is implementation-defined behavior
this is undefined behavior


[ - ]
Comment by tkendelMay 19, 2023

It is instructive if you compile with "--std=cXX -O2" and compare the outcomes; same compiler, just different versions of the standard.

With clang on macOS, for c99 I get an infinite loop, with c11, I get SIGILL at runtime (everything else being the same).  Without optimization, I get 2147483647 for both.

Note, since it is "undefined behavior", all of the above outcomes are valid!  It could have been 42!  (Someone should suggest that to the clang developers as an easter egg.)

Now, looking at the success rate that keeps hovering around 20%... hmm, let's see, you offered 5 answers to choose from... a random generator couldn't have done worse!  LOL

[ - ]
Comment by othmaneMay 19, 2023

maybe add some volatile tag for the i variable will avoid the compiler optimization and this will go for the limit 0x80000000

[ - ]
Comment by jms_nhMay 19, 2023

Volatile won't "fix" the impact of undefined behavior.

[ - ]
Comment by cpnsMay 18, 2023

The Compiler Explorer link links to unrelated code.

Although this has not changed, quoting a draft of an antique version of the standard lacks rigour.  I appreciate that you don't really want to purchase the standard just for this of course.

In the instance where compilers optimised out the code entirely, did you assign the return value to a volatile, or do anything with the result?  Code that does nothing can clearly be optimised to nothing. That would not be an exemplar of what the function does, but rather of the program as a whole.

[ - ]
Comment by jms_nhMay 18, 2023
The Compiler Explorer link links to unrelated code.

I only linked to godbolt.org, which is the entry point to Compiler explorer. If you are seeing unrelated code then either it is the default ("int square(int num) { ...") or something that you already were using in Compiler Explorer.

Although this has not changed, quoting a draft of an antique version of the standard lacks rigour. I appreciate that you don't really want to purchase the standard just for this of course.

It's not just about whether I don't want to purchase the standard. I want readers to be able to view the standard itself. I chose N1256 because it is the basis of C99, which is likely the most generally used version of C in embedded systems. (C89 and C11 would be older and newer fringes.) If you want a resource of the various draft standards on which the actual standard: https://stackoverflow.com/questions/81656/where-do...

N1570 (C11) has the exact same text for undefined behavior as N1256: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n...

In the instance where compilers optimised out the code entirely, did you assign the return value to a volatile, or do anything with the result? Code that does nothing can clearly be optimised to nothing. That would not be an exemplar of what the function does, but rather of the program as a whole.

I compiled exactly the code I posted, which is a valid translation unit (compilation unit) in its own right. The compiler cannot optimize out a function in a translation unit which may have potential linkage from another translation unit.

[ - ]
Comment by KocsonyaMay 19, 2023

I do have the final standard (purchased it). It is actually pretty much the same as the final draft, the differences are mostly just fixing punctuation and the like.

However, the scary stuff about undefined behaviour is that

1) the compiler is allowed to do whatever it likes

2) the compiler is not obliged to tell you that it did so

This is what the standard says:

3.4.3 

1 undefined behavior 

behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements

2 NOTE Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).

3 EXAMPLE An example of undefined behavior is the behavior on integer overflow.

Note that in NOTE they tell you "ranging from ... to ... to" leaving the exact definition open to interpretation. In fact, the standard does specify that it "imposes no requirements". The compiler can do anything whatsoever and silently so.

Then Annex J.2 lists the undefined behavior conditions. The list is about 13 pages long. Most of them are obvious and any sane compiler will actually flag them as error, but there are a couple of really insidious booby-traps hiding there too.

[ - ]
Comment by conelecMay 21, 2023

Logic dictates that there can be no such thing as "Undefined Behavior". It is most likely the person writing the segment of code has just written nonsense and doesn't understand how to write C code. I am guilty of this as well. That's why we learn and should never be too old to do so. There is often the case where you think you know how something works but are never 100% sure. This is as good as knowing nothing. You either know or you don't. Guessing is not an option. Leave the guessing up to Microsoft operating systems writers. There is no detailed explanation of why this code fails. Is it because the pre increment should have been post increment? From my perspective I can see what the intention of the code is. Problems always arise when programmers try and be too smart for their own good. Keep it simple and easy to understand.

[ - ]
Comment by jms_nhMay 21, 2023

Read the C standard. You need to know what undefined behavior means and how to avoid it.

To post reply to a comment, click on the 'reply' button attached to each comment. To post a new comment (not a reply to a comment) check out the 'Write a Comment' tab at the top of the comments.

Please login (on the right) if you already have an account on this platform.

Otherwise, please use this form to register (free) an join one of the largest online community for Electrical/Embedded/DSP/FPGA/ML engineers: