Author Topic: An 'interesting' thing you can do in C++  (Read 18735 times)

0 Members and 1 Guest are viewing this topic.

Offline GeorgeOfTheJungle

  • Super Contributor
  • ***
  • !
  • Posts: 2699
  • Country: tr
Re: An 'interesting' thing you can do in C++
« Reply #125 on: September 13, 2018, 12:25:10 pm »
Quote
The result was that a block local variable would keep its random uninitialized value.
If a was uninitialized before that line, it would have to remain so after it, so that's ok, isn't it?
IIRC, it was along the lines of y[n] = z[n++], with 'y' a local array.
It was definitely not OK...

Ok, good, but then that's not the "a= a++;" we were talking about!
The further a society drifts from truth, the more it will hate those who speak it.
 

Offline GeorgeOfTheJungle

  • Super Contributor
  • ***
  • !
  • Posts: 2699
  • Country: tr
Re: An 'interesting' thing you can do in C++
« Reply #126 on: September 13, 2018, 12:29:56 pm »
"a = a++;" is perfectly valid C code.

Syntactically yes, but semantically it's... ambiguous.
« Last Edit: September 13, 2018, 12:43:27 pm by GeorgeOfTheJungle »
The further a society drifts from truth, the more it will hate those who speak it.
 

Offline macboy

  • Super Contributor
  • ***
  • Posts: 2254
  • Country: ca
Re: An 'interesting' thing you can do in C++
« Reply #127 on: September 13, 2018, 02:09:01 pm »
Why do you feel "break" is evil?

Totally beats me. That's what everybody were taught, on compulsory programming introduction courses (in C++), in the university I attended. (To be fair, we were actually taught that "break" is not as Evil as goto or ?:, but still a bit Evil.)

Of course, writing practical code in real life while completely avoiding ?: or break or even goto is nearly impossible, or at least detrimental to code quality and readability, as well as psychological productivity.

That said, now I remembered an additional detail: they had an exception that it is allowed to use break inside switch-case, but only there. They figured out switch-case doesn't work without it, and were not bold enough to claim switch-case is Evil.

This is all  :-DD , but at the same time, it's quite  :-- as well.

(Also note that creating such "order" of Evil-ity is ridiculous. In some contexts, goto results in much more readable result than break, yet it's down the list of things to be "frowned upon". It's always dependent on usage. But I guess we have no debate about this here.)
I have no qualms about using break (or even continue) but only in cases where it makes the program flow easier to construct and easier to read/understand. Yes there are such cases.  Especially when writing low level code as I do, there are times when you need to terminate a loop "early" due to some unforeseeable error and/or timing information from hardware.  My use of continue is much more rare, but there are occasions where it, too, just makes sense. I have literally never used a goto in C/C++, and never will. I cringe when I see one. On the other hand, when writing assembly code, program flow essentially all boils down to goto/branch statements, so that's that.

I restrict use of ?: to where it makes code cleaner. A prime example is where I check a flag and print a different substring based on it. e.g.:
Code: [Select]
printf("some operation state is %s\n", (someState == state_invalid_c)? "Invalid" : "OK");I like this better than printing the first part of the string, then doing a if/else to print one of the two different status strings.
 

Offline RoGeorge

  • Super Contributor
  • ***
  • Posts: 6185
  • Country: ro
Re: An 'interesting' thing you can do in C++
« Reply #128 on: September 13, 2018, 02:33:49 pm »
Once I counted how many goto were in the Linux Kernel.  I don't remember the number, but there were A LOT of goto lines.

Offline GeorgeOfTheJungle

  • Super Contributor
  • ***
  • !
  • Posts: 2699
  • Country: tr
Re: An 'interesting' thing you can do in C++
« Reply #129 on: September 13, 2018, 02:39:57 pm »
There's a (name hidden) database for the Mac with a Pascal-like language that has no return nor break nor continue nor of course goto.
The further a society drifts from truth, the more it will hate those who speak it.
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3140
  • Country: ca
Re: An 'interesting' thing you can do in C++
« Reply #130 on: September 13, 2018, 03:00:46 pm »
That one is fairly classic, the other good one is that if you do a pointer null check after dereferencing the pointer the compiler is free to take the fact that you have dereferenced the pointer as guaranteeing that the pointer is non null.

x=p->foo;
if (p == NULL){...... // This block will be removed as dead code because the dereference above says that p cannot be null without involving UB.

Yes, the null check was in the wrong place, but the some of the security types still got sniffy when this behaviour was introduced.

Compilers are very good at optimizing horrible code because it's easy to do. And, over the years, they find newer and better ways to do this. Not so much with reasonably well-written code.
 

Offline Bassman59

  • Super Contributor
  • ***
  • Posts: 2501
  • Country: us
  • Yes, I do this for a living
Re: An 'interesting' thing you can do in C++
« Reply #131 on: September 13, 2018, 05:55:50 pm »
"a = a++;" is perfectly valid C code.

Syntactically yes, but semantically it's... ambiguous.

For what it's worth, Xcode (which uses LLVM) puts up a warning as soon as you type the line.

 
The following users thanked this post: MK14

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4028
  • Country: nz
Re: An 'interesting' thing you can do in C++
« Reply #132 on: September 13, 2018, 09:37:58 pm »
Nope, I'm with brucehoult on this one, our mothers are safe.
I'm partially in total disagreement.
Our mothers might be safe, but hyperbole is a man's best friend.

Unfortunately I have lost the example (code, specific version of gcc and flags used) where a similar line was completely ignored by the compiler.
Skipped, no code emitted, no warning.
The result was that a block local variable would keep its random uninitialized value.

That's absolutely fair. If a has an undefined value then so does a++.
 

Offline MK14

  • Super Contributor
  • ***
  • Posts: 4527
  • Country: gb
Re: An 'interesting' thing you can do in C++
« Reply #133 on: September 14, 2018, 04:39:28 pm »
Let's ask an extreme world class expert on compiler design (particularly C and C++), if UNDEFINED, can do ANYTHING, or if it is limited to one or two reasonable/obvious values ?

"Hello, Dr GCC, can you please answer this question for us" ?

Here is my program...

#include <stdio.h>

int i;

int main(void)
{
  i = 0;
  i *= (i *= ++i) * (i *= i) * (i *= i) * (i *= i) * (i *= ++i);
  printf("\nDemo1 = i = %d\n", i);

  i = 0;
  i *= (i *= ++i) * (i *= i) * (i *= ++i) * (i *= i) * (i *= ++i);
  printf("\nDemo2 = i = %d\n", i);
}

"So, Dr GCC, what is the answer" ?

gcc eevblog.c -oeevblog
./eevblog
"No flags were changed from default, and no errors or warnings came up"

Demo1 = i = 0

Demo2 = i = -1554387584

"Thanks, DR GCC".

tl;dr
Going from 0, to -1554387584, because of one extra ++, in the middle of an expression (disappointingly, GCC (very recent version) gave no warnings or errors). Seems to me (and Dr GCC), that ANYTHING, can happen, when you use UNDEFINED things in your programs.

Now, to really prove a point. Let's do it again, and just tidy up the code. The results will be the same, surely ?

#include <stdio.h>
int main(void)
{
  int i = 0;
  i *= (i *= ++i) * (i *= i) * (i *= i) * (i *= i) * (i *= ++i);
  printf("Demo1 = i = %d\n", i);
  i = 0;
  i *= (i *= ++i) * (i *= i) * (i *= ++i) * (i *= i) * (i *= ++i);
  printf("Demo2 = i = %d\n", i);
}

gcc eevblog.c -oeevblog
./eevblog
                               ..."Again, no errors or warnings"
Demo1 = i = 0
Demo2 = i = -368195456

So ANYTHING has changed its mind, again. Just because the variable was moved from globals to locals (presumably).
« Last Edit: September 14, 2018, 04:43:34 pm by MK14 »
 

Offline GeorgeOfTheJungle

  • Super Contributor
  • ***
  • !
  • Posts: 2699
  • Country: tr
Re: An 'interesting' thing you can do in C++
« Reply #134 on: September 14, 2018, 05:01:39 pm »
Use -Wsequence-point

kk.c: In function ‘main’:
kk.c:6: warning: operation on ‘i’ may be undefined
kk.c:9: warning: operation on ‘i’ may be undefined
The further a society drifts from truth, the more it will hate those who speak it.
 
The following users thanked this post: MK14

Offline MK14

  • Super Contributor
  • ***
  • Posts: 4527
  • Country: gb
Re: An 'interesting' thing you can do in C++
« Reply #135 on: September 14, 2018, 05:07:42 pm »
Use -Wsequence-point

kk.c: In function ‘main’:
kk.c:6: warning: operation on ‘i’ may be undefined
kk.c:9: warning: operation on ‘i’ may be undefined

Originally, I was using -Wall and had the optimiser on (-O3), which also produced the warnings and the same results, at least for the first program.
But I removed any unnecessary clutter, to reduce the size of the demo program, for the forum post.
 

Offline MK14

  • Super Contributor
  • ***
  • Posts: 4527
  • Country: gb
Re: An 'interesting' thing you can do in C++
« Reply #136 on: September 14, 2018, 08:15:06 pm »
The code for the second program is typed in and ready for anyone to try or change (press FORK-THIS), online, here:
https://onlinegdb.com/HyBUB9KuQ

Code: [Select]
#include <stdio.h>
int main()
{
  int i = 0;
  i *= (i *= ++i) * (i *= i) * (i *= i) * (i *= i) * (i *= ++i);
  printf("Demo1 = i = %d\n", i);
  i = 0;
  i *= (i *= ++i) * (i *= i) * (i *= ++i) * (i *= i) * (i *= ++i);
  printf("Demo2 = i = %d\n", i);
}

Results:
Code: [Select]
Demo1 = i = 0                                                                                                                 
Demo2 = i = -368195456                                                                                                         
...Program finished with exit code 0                                                                                           
Press ENTER to exit console

« Last Edit: September 14, 2018, 08:24:58 pm by MK14 »
 

Offline MK14

  • Super Contributor
  • ***
  • Posts: 4527
  • Country: gb
Re: An 'interesting' thing you can do in C++
« Reply #137 on: September 14, 2018, 08:49:54 pm »
If you change the variable type to double, and initial value to pi. Done here:
https://onlinegdb.com/ryiQCqY_Q]
It goes even crazier.
Demo1 = i = 84465015249278344875802672090097198053720064.000000                                                     
Demo2 = i = 446308403328.000000

Demo1, rapidly increases if you increase the initial value, yet demo2 remains apparently constant.
Weird, really weird.
« Last Edit: September 14, 2018, 08:51:41 pm by MK14 »
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4028
  • Country: nz
Re: An 'interesting' thing you can do in C++
« Reply #138 on: September 14, 2018, 10:17:48 pm »
Let's ask an extreme world class expert on compiler design (particularly C and C++), if UNDEFINED, can do ANYTHING, or if it is limited to one or two reasonable/obvious values ?

You put 12 (or 13) arithmetic operations between your sequence points, with 2 (or 3) of those operations having side-effects. The compiler is limited to doing those operations, in some order.

The result is going to be some number.

The result is *not* going to be your computer catching on fire.
 
The following users thanked this post: hans, MK14

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4028
  • Country: nz
Re: An 'interesting' thing you can do in C++
« Reply #139 on: September 14, 2018, 10:29:18 pm »
If you change the variable type to double, and initial value to pi. Done here:
https://onlinegdb.com/ryiQCqY_Q]
It goes even crazier.
Demo1 = i = 84465015249278344875802672090097198053720064.000000                                                     
Demo2 = i = 446308403328.000000

Demo1, rapidly increases if you increase the initial value, yet demo2 remains apparently constant.
Weird, really weird.

446308403328 is 2^7 * 3^20.  446308403328 % 2^32 - 2^32 = -368195456

Nothing strange here, it's just the result of incrementing 0 twice and three times and doing a little multiplying and squaring -- exactly as you told it to. And then truncating the answer to a 32 bit signed integer.
 
The following users thanked this post: MK14

Offline MK14

  • Super Contributor
  • ***
  • Posts: 4527
  • Country: gb
Re: An 'interesting' thing you can do in C++
« Reply #140 on: September 14, 2018, 10:30:56 pm »
The result is *not* going to be your computer catching on fire.

It depends on the computer hardware, and what it is connected to.
If it is an autonomous self-driving car, driving at high speed on a motorway.
Then it could cause an accident, which results in the vehicle (and hence the computer), catching on fire.

But I agree, in general, in most cases, serious software bugs, will not (usually) set the computer on fire.
 

Offline MK14

  • Super Contributor
  • ***
  • Posts: 4527
  • Country: gb
Re: An 'interesting' thing you can do in C++
« Reply #141 on: September 14, 2018, 10:40:58 pm »
446308403328 is 2^7 * 3^20.  446308403328 % 2^32 - 2^32 = -368195456

Nothing strange here, it's just the result of incrementing 0 twice and three times and doing a little multiplying and squaring -- exactly as you told it to. And then truncating the answer to a 32 bit signed integer.

Thanks for giving that insight. I did not realise, that is what it was doing.
But I still believe that since it is "undefined", it should NOT be used in normal/real coding practice.

Also, if you change the language (but keep the source code the same), via those online links I posted. Those numbers, change quite a lot, between C and C++, language selections!

Since i starts out as 0 (in earlier programs), and it is basically i *= ... lots of stuff ***
It possibly should be evaluating to 0 (basic maths 0 x stuff = 0).
But I am NOT familiar enough with the full C and C++ language specifications, to know how it is suppose to handle that situation.
Presumably, because -Wall, says UNDEFINED. It is undefined, and can be anything it likes.

EDIT: Original(C): https://onlinegdb.com/HyBUB9KuQ
Demo1 = i = 0                                                                                                       
Demo2 = i = -368195456
...Switching language  to C++ https://onlinegdb.com/Sy1pRhYOX , source code kept same.
...Results now have changed to (via C to C++ language switch) ...
Demo1 = i = 16                                                                                                                 
Demo2 = i = 5345344

In my perception (ignoring UNDEFINED means ANYTHING can happen),
going from C to C++ (source code kept IDENTICAL), should not really change the output values.
But I guess some of the changes between C and C++, have caused this, so it is not unreasonable, just a bit weird.
« Last Edit: September 14, 2018, 11:08:59 pm by MK14 »
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4028
  • Country: nz
Re: An 'interesting' thing you can do in C++
« Reply #142 on: September 14, 2018, 11:09:31 pm »
The code for the second program is typed in and ready for anyone to try or change (press FORK-THIS), online, here:
https://onlinegdb.com/HyBUB9KuQ

Code: [Select]
#include <stdio.h>
int main()
{
  int i = 0;
  i *= (i *= ++i) * (i *= i) * (i *= i) * (i *= i) * (i *= ++i);
  printf("Demo1 = i = %d\n", i);
  i = 0;
  i *= (i *= ++i) * (i *= i) * (i *= ++i) * (i *= i) * (i *= ++i);
  printf("Demo2 = i = %d\n", i);
}

Results:
Code: [Select]
Demo1 = i = 0                                                                                                                 
Demo2 = i = -368195456                                                                                                         
...Program finished with exit code 0                                                                                           
Press ENTER to exit console

I get exactly the same result with gcc for any of i386, RISC-V or ARM.

I get exactly the same result with -O0 (in which case the arithmetic is done at runtime, in main) or with -O1 (in which case the arithmetic is done by the compiler and the answer is simply printed.

Here is the RISC-V code for -O0. The others are the exact equivalent. They just keep some temporary values in registers and save and load values of i to its stack slot in memory.

Code: [Select]
# i=0
sw      zero,-20(s0)

lw      a5,-20(s0)
addi    a5,a5,1
sw      a5,-20(s0)
lw      a3,-20(s0)
lw      a5,-20(s0)
addi    a5,a5,1
sw      a5,-20(s0)
lw      a4,-20(s0)
lw      a5,-20(s0)
addi    a5,a5,1
sw      a5,-20(s0)
lw      a5,-20(s0)
lw      a2,-20(s0)
mul     a3,a2,a3
sw      a3,-20(s0)
lw      a2,-20(s0)
lw      a3,-20(s0)
mul     a3,a2,a3
sw      a3,-20(s0)
lw      a2,-20(s0)
lw      a3,-20(s0)
mul     a3,a2,a3
lw      a2,-20(s0)
mul     a4,a2,a4
sw      a4,-20(s0)
lw      a4,-20(s0)
mul     a3,a3,a4
lw      a2,-20(s0)
lw      a4,-20(s0)
mul     a4,a2,a4
sw      a4,-20(s0)
lw      a4,-20(s0)
mul     a4,a3,a4
lw      a3,-20(s0)
mul     a5,a3,a5
sw      a5,-20(s0)
lw      a5,-20(s0)
mul     a5,a4,a5
lw      a4,-20(s0)
mul     a5,a4,a5
sw      a5,-20(s0)

#print
lw      a1,-20(s0)
lui     a5,0x1b
addi    a0,a5,2016 # 1b7e0 <__clzsi2+0x4a>
jal     1044e <printf>

Clang gives a different answer to gcc (5345344 = 2^6 * (2^4 + 1)^4) , but it gives the same answer across different CPU types and different optimisation levels, and again does the actual calculation in machine code with -O0 but just prints the final answer directly with -O1.

While you might not find the answer easy to predict, it seems there really are only a couple of likely answers. Certainly no explosions.
 
The following users thanked this post: MK14

Offline MK14

  • Super Contributor
  • ***
  • Posts: 4527
  • Country: gb
Re: An 'interesting' thing you can do in C++
« Reply #143 on: September 14, 2018, 11:16:45 pm »
Wow, that's an amazing piece of work you have just done.

I can now better understand, your point of view.

C/C++ source code, changing its behaviour, between GCC, CLANG and presumably other compilers. Would still cause all sorts of practical difficulties, and the immense difficulty in predicting what the code really does (how it gets to the answers), would make it a nightmare or at least difficult/tricky to change in the future.

But having primarily two different values, is not impossible to handle.
E.g. Conditional Compiling and/or early tests in the source code to see which way round such things will be handled by the compiler.

A bit like, C/C++, is a bit weak as regards if the integer default is 32 or 64 bits.
So, some clever source code systems, do some checks early on and set things up, so it can handle the various possibilities.

Just to be clear. I still think UNDEFINED is a bad idea to code with, and can still potentially cause at least two different outcomes. Presumably it still can be ANYTHING, but you have presented some nice arguments as to why it may be often less than anything.
« Last Edit: September 14, 2018, 11:21:31 pm by MK14 »
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4028
  • Country: nz
Re: An 'interesting' thing you can do in C++
« Reply #144 on: September 15, 2018, 12:32:28 am »
Wow, that's an amazing piece of work you have just done.

I can now better understand, your point of view.

C/C++ source code, changing its behaviour, between GCC, CLANG and presumably other compilers. Would still cause all sorts of practical difficulties, and the immense difficulty in predicting what the code really does (how it gets to the answers), would make it a nightmare or at least difficult/tricky to change in the future.

It's a VERY VERY bad idea to write code like that. It's bad programming.

But you wrote three of ++i and there are three of "addi x,y,1" in the generated code.
You wrote ten of "*" or "*=" and there are ten "mul" in the generated code.

All that changes is the order of those thirteen operations and which results are saved and used again later, and when.

I don't know how many reasonable answers there are. It's probably dozens or hundreds. But the answer is a number, not an explosion.

I've shown that if you use the same compiler (and compiler version) across different CPU types you'll get the same answer. Different compilers can produce different answers, but there are't a lot of different compilers in use these days.

Different versions of the same compiler *could* produce different answers, but this will be less common. The gcc versions I used were 7.3.0 for i386 and ARM, and 7.2.0 for RISC-V. I just tried another x86 machine with gcc 5.4.0 and got the same answer (and the same for both i386 and x86_64)

As you showed, you also get the same answer for int and for double precision FP, once you take into account the range limitations of int. The same operations are done in the same order.

But anyway DON'T CODE LIKE THIS!! Don't use ++ or -- on a variable if that variable appears more than once in the statement (right AND left sides).
 
The following users thanked this post: hans, MK14

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4028
  • Country: nz
Re: An 'interesting' thing you can do in C++
« Reply #145 on: September 15, 2018, 12:49:01 am »
EDIT: Original(C): https://onlinegdb.com/HyBUB9KuQ
Demo1 = i = 0                                                                                                       
Demo2 = i = -368195456
...Switching language  to C++ https://onlinegdb.com/Sy1pRhYOX , source code kept same.
...Results now have changed to (via C to C++ language switch) ...
Demo1 = i = 16                                                                                                                 
Demo2 = i = 5345344

16 and 5345344 are the same answers clang gets for both C and C++, for all CPU types I tried. It's an interesting question why gcc and g++ would get different answers.
 
The following users thanked this post: MK14

Offline MK14

  • Super Contributor
  • ***
  • Posts: 4527
  • Country: gb
Re: An 'interesting' thing you can do in C++
« Reply #146 on: September 15, 2018, 02:06:44 am »
16 and 5345344 are the same answers clang gets for both C and C++, for all CPU types I tried. It's an interesting question why gcc and g++ would get different answers.

Another AMAZING change of value (which the concept is very likely to be how you described, where it is changes in order of the calculations, has a big impact on the final answers), is when you leave the source code unchanged.
Except for where the integer variable i, is declared. Between before main(), and declaring it within the main() {} codeblocks.

When it is before main(), the value changes to (as detailed in a much earlier post of mine, in this thread):
Demo1 = i = 0
Demo2 = i = -1554387584

EDIT: Unable to reproduce these strange values, using the online compiler, as it comes up with the same values as before. But I can still reproduce these values by using my local Linux machines GCC version:
Code: [Select]
gcc --version
gcc (Ubuntu 7.3.0-16ubuntu3) 7.3.0
So it is probably because the online version uses strange memory models,
or my local GCC has bug(s), applicable to this issue or some other explanation.
End of EDIT.

I'm amazed, that just changing where/how an integer is declared, changes its calculated value, like that.

Usually, such a change in allocation, would be invisible to the C/C++ code. Unless other C/C++ files attempt to access the variable and/or its operations are timed extremely carefully. I've seen slight (tiny) timing variations, because it is on the stack, heap, somewhere in memory or in registers, depending on the compiler, cpu, implementation, optimisation level, etc.

Maybe it is a "race hazard", between different initialisation sections of the C/C++ code, or other peculiarities ?
But there are many other possible explanations.

If I get the inclination, I may spend time, and try and find out why this happens.
« Last Edit: September 15, 2018, 02:35:06 am by MK14 »
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4199
  • Country: us
Re: An 'interesting' thing you can do in C++
« Reply #147 on: September 15, 2018, 03:32:32 am »
I've noticed an annoying trend.
In the old days, if you used an ambiguous syntax that the spec claimed was "undefined", you would tend to get a result that made sense, more or less.  It might not be the same on all systems and all compilers, but each result would be ... sensible, looked at from some perspective.
More recently, less so.  The compiler developers mumble about optimization and etc, but I think they're doing it out of spite.
Some of the cases are particularly annoying to embedded developers.I've run into situation where common constructs no longer work as expected:
Code: [Select]
uint8_t time = 0 - delaytime;while (++time != 0) {    //stuff.}"The behavior of C WRT integer overflow is undefined.  The compiler decided that incrementing a non-zero value would never reach 0, and made the loop unconditional and infinite."

Code: [Select]
   while (1);   // stop the program"A while loop may be assumed to terminate.  Since the loop is empty and doesn't do anything, the code was entirely omitted."
https://stackoverflow.com/questions/16436237/is-while1-undefined-behavior-in-c

Grr.
 
The following users thanked this post: oPossum, MK14

Offline newbrain

  • Super Contributor
  • ***
  • Posts: 1719
  • Country: se
Re: An 'interesting' thing you can do in C++
« Reply #148 on: September 15, 2018, 11:49:30 am »
I've noticed an annoying trend.
In the old days, if you used an ambiguous syntax that the spec claimed was "undefined", you would tend to get a result that made sense, more or less.  It might not be the same on all systems and all compilers, but each result would be ... sensible, looked at from some perspective.
More recently, less so.  The compiler developers mumble about optimization and etc, but I think they're doing it out of spite.
Some of the cases are particularly annoying to embedded developers.I've run into situation where common constructs no longer work as expected:
Code: [Select]
uint8_t time = 0 - delaytime;while (++time != 0) {    //stuff.}"The behavior of C WRT integer overflow is undefined.  The compiler decided that incrementing a non-zero value would never reach 0, and made the loop unconditional and infinite."

Code: [Select]
   while (1);   // stop the program"A while loop may be assumed to terminate.  Since the loop is empty and doesn't do anything, the code was entirely omitted."
https://stackoverflow.com/questions/16436237/is-while1-undefined-behavior-in-c

Grr.
I'm a bit puzzled by both of these statements:
  • The behaviour of overflow in unsigned integral types is actually well defined (that's the major point for using them, IMO), optimising that away it's simply wrong.
    If someone uses a signed integer there, it's their fault.
  • while(1) does not fall in the 6.8.5/6 clause added in C11, so it has defined (and expected) behaviour.
    That clause refers to loops where the controlling expression is not a constant expression (and etc. etc.)*.
    One of the good reason to use a volatile object.
    But, yes, an earlier version was more problematic.

If they are doing that out of spite for the use of well known undefined constructs, I'm with them.
Better fail in a more visible way rather than instilling a misleading sense of confidence on behaviour that is not guaranteed in any way.
I actually would make your sound card go , and declare that a diagnostic (not that one is needed with UB).

And now is the time for the dreaded, misleading and easily rebuttable car analogy:
Using UB is like driving on the highway in the wrong direction. You might survive it, but it's something you should strive to avoid.

* Note: I only have access to the final draft of C11 (n1570), not the actual standard. That draft was approved without remarks, AFAIK.
« Last Edit: September 15, 2018, 12:01:28 pm by newbrain »
Nandemo wa shiranai wa yo, shitteru koto dake.
 
The following users thanked this post: MK14

Offline GeorgeOfTheJungle

  • Super Contributor
  • ***
  • !
  • Posts: 2699
  • Country: tr
Re: An 'interesting' thing you can do in C++
« Reply #149 on: September 15, 2018, 02:40:57 pm »
Code: [Select]
#include <stdio.h>
int main()
{
  int i = 0;
  i *= (i *= ++i) * (i *= i) * (i *= i) * (i *= i) * (i *= ++i);
  printf("Demo1 = i = %d\n", i);
  i = 0;
  i *= (i *= ++i) * (i *= i) * (i *= ++i) * (i *= i) * (i *= ++i);
  printf("Demo2 = i = %d\n", i);
}

I've tried out of curiosity and using int* i= malloc(sizeof(int)); and *i everywhere instead of i, it always gives 0 no matter what, with gcc in Intel and ARM.
The further a society drifts from truth, the more it will hate those who speak it.
 
The following users thanked this post: MK14


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf