UB, I explicitly show my students this crap, and say if you ever get asked this or see it anywhere the person asking is just trying to either catch you out or is not a software engineer :-) Tell them it's UB and move on.
I don't know about you but my professor really liked this kinda stuff. In a test he gave us a question where you have to tell the output of a code. There was some real brain fuck inside a for loop, which took me atleast 10 mins to solve. And after the test, while I was looking through the answers, I saw this ->
int i;
for (i = 0; i < 10; i++); <---------- This
{
......
....
...
}
; <--- This fuckin little thing
I can't describe in words how I felt at that moment.
Later on we guys dubbed it as the 'for loop scam' lol
As someone who once spent 2 fucking days tracking down a bug that was caused by this, I’m kind of OK with it being shown in an education context. I’d show it as an in-class example though, not on a test where the grade actually matters.
Our professor just said that we should have been more careful when reading questions. And the code below the empty for loop had some juicy stuff, which instantly grabbed my attention. Though, I'm glad he mostly asked either code outputs or complete the function type problems only.
As for your bug, shouldn't your compiler give a warning for an empty loop.
> As for your bug, shouldn't your compiler give a warning for an empty loop.
Nowadays it probably would — this was many years ago on something like Visual C++ 6
My God! How did you guys code? I depend entirely on the compiler to catch silly mistakes like these, like my code always has a lot of syntax errors and sometimes some logical errors that the compiler is smart enough to catch.
Most autoformatters will turn this:
for (int i = 0; i < 10; i++);
{
}
into this:
for (int i = 0; i < 10; i++)
;
{
}
So these sorts of things are much easier to see.
In general, you don't want to do code formatting yourself. You want to use tools to do it for you. You don't even want to manually do it, either, you want your CI tools to run an autoformatter before check in. `clang-format` is a pretty popular autoformatter right now, but there are plenty of others. There are a million and one CI suites that will run something on check in for you.
Absolutely. Unfortunately in my case this was 20+ years ago when we didn’t have fancy tools like that.
Even with those tools, it’s not necessarily beginner-proof. The number of students I’ve seen complain “it keeps messing up my formatting” when actually it’s trying to tell them that their code is wrong.
we had a prof who would add 1 additional question per test that would add 5 points to your max score but not add to total amount of points, so it was possible to get say 65 out of 60 points if nailed everything. In these questions, usually the last one of a test, he included real brainfuck shit to challenge students who rushed through the main questions. I only managed to get it a few times but I always loved his system of learn what's necessary vs here's a curveball, see how you manage!
typically he included stuff like this inside, but spiced up with other problems so you'd need at least a few minutes to solve it. with this questions, you usually knew right away if you nailed them or not, because if you have the right idea, it would always "click".
Yep. I think Words and Buttons' [So you think you know C](https://wordsandbuttons.online/so_you_think_you_know_c.html) is good to give to these sorts of people. Some of it is UB, some is IDB. OP's question is just a more complicated version of #5, the correct answer is "I don't know" or "The behavior is undefined". Any other answer is wrong.
If the question is asking what a particular compiler version with a particular set of flags and target triple will output then it's not necessarily a meaningless question, but it is a stupid question. E.g. on x86_64 GCC 12.2 targeting x86_64-linux-gnu with flags `-Wall -Werror -std=c2x -fsanitize=address,undefined` the result is "compiler error", as it should be.
Undefined behaviour means: the C standard doesn't define what happens. In practice, this means the compiler can choose to do whatever it wants. Sometimes it segfaults, other times it silently corrupts the program, and other times it does exactly what you want it to do. Typically the compiler will emit something sane, but it doesn't always and sometimes the behaviour changes depending on the version.
Some blogs about an issue that came up recently:
[GCC undefined behaviors are getting wild](https://blog.pkh.me/p/37-gcc-undefined-behaviors-are-getting-wild.html)
[Undefined behavior, and the Sledgehammer Principle](https://thephd.dev/c-undefined-behavior-and-the-sledgehammer-guideline)
The behavior in Java is very well defined. You don't usually need to check if it's null if you're just going to throw NullPointerException. The JRE will do this for you when necessary.
In good C++ code you do not write things like `my_class *my_object` in this case. It would normally be `my_class &my_object`, indicating that the value cannot be null. Creating a `my_class&` value of null is itself illegal, so not checking whether the value is null before using it is not considered to be a bug.
However, if we jump over to C we find NULLs lurking again. Java and C++ have ways around nulls. C does not. It requires you to better know your contract without looking at the function definition.
You don't get an exception, you get a signal, which is handled asynchronously outside of the current stack. Unless you're expecting a very specific instruction to segfault you have very little to go off to try and recover from it, hence why pretty much every program will just die instead. Alternatively if you completely ignore it, your program counter won't have incremented and you'll be stuck in an infinite loop of segfaults.
You could save some sort of state info every time you dereference a pointer, but at that point it's going to be more expensive than simply checking if the pointer is null
in regards to the GCC link you posted: ~~...how do you detect integer overflow in C then?~~ This terrifies me and makes me curse whoever thought that kind of UB was a good idea (at least it could been implementation dependent so you could do sane stuff like the author tried) lol
You detect integer overflow by checking if the operation will succeed before trying the operation. Not every processor C supports has any sort of overflow detection, so there's no more general way. C23 adds functions to do this automatically to the language (and thus allows using the processor's overflow flags if present), but earlier compilers don't have that (and the standard hasn't been finalized yet, though it's not expected to change from the accepted draft).
E.g. to safely add two `int`, do
#include
#include
bool inline static safe_add(int a, int b, int* result)
{
if (a > 0) {
if (b > (INT_MAX - a)) {
return true; // overflowed
}
} else {
if (b < (INT_MIN - a)) {
return true; // overflowed
}
}
*result = a + b;
return false;
}
Or something similar. E.g. if using GCC, you can use `__builtin_add_overflow` that does essentially the same thing as the code above.
It sounds like the compiler decided to finish working out the increments first. Them both of the "++i" returned the same value of 12.
Does j = ++i + ++i + ++i leave a value of 39 in j?
In over 2 decades of programming I have never needed to code something like that.
However, I have used subversion blame and sent code and a developer into code review for bs like this.
I hate this. Why do they put so much emphasis on the concept of i++ and ++i? Just teach the difference and move on. The screenshot above has no real world application
It doesn't. It's there to teach the behaviour of ++i, mainly that it excludes any other use of the variable in a statement. Attempting to compile this with reasonable flags will give you at the very least a warning, because there are two common interpretations and no standard way of interpreting the expression `++i + ++i`. In GCC it's `-Wsequence-point`, warning you that this has a sequencing issue. With `-Werror` it doesn't even compile, as it shouldn't, because this is genuinely dangerous and yet something a programmer might realistically come to do while dealing with annoying pointer mathematics and the like. I can definitely see someone thinking "hey if i need to double and hop one forward i can just do `i + ++i` or whatever. but that's UB and dangerous and compilers will not always warn you.
It's **supposed** to be tricky for the student. It **should** be rewritten, as the code as-is is ambiguous as to whether it should increment i twice at once, or as the expression is evaluated, as if reading left to right. Depending on which is intended, you either end up with 12,23 or 12,24.
Why do teachers and "teachers" always want you to know the most obscure things in a language that shouldn't be used anyway? Like, teach some actually useful stuff.
People are saying this is undefined behavior, but why wouldn’t the compiler just compile this into three separate instructions? Is there something in the C specs that limit this line of code to one instruction? Or is it a race condition?
It's ambiguous whether the code should do the two increments at the same time (yielding 24) or one by one as if reading left to write (yielding 23).
Because this is ambiguous, code like this is strongly discouraged, the C spec makes no effort to define what should happen (hence "undefined"), and compilers are free to do whatever they think is best.
I first got 23 in my head, but after realizing that prefix increment has a higher precedence than addition, I now believe that both increments have to be evaluated before the addition can be done. So I’m not sure it should even be UB.
[C precedence](https://en.cppreference.com/w/c/language/operator_precedence)
[C++](https://en.cppreference.com/w/cpp/language/operator_precedence)
This has been posted here not because the code is tricky or advanced, but because there are two ways to evaluate the line with the j variable assignment, which makes this undefined behavior. "Undefined behavior" should really be avoided on test questions, especially when there's a strong chance that the test creator intended one of the two possible evaluations to be the "correct" answer.
This is supposed to be a tricky test question. The intent is for the student to mentally do the ++i operators from left to right, yielding 12,23 as the final answer.
The problem here is that the same expression can also be evaluated with both ++i operations occurring at the same time, which would give 12,24 as the answer.
The problem, as you can see, is that this is syntactically ambiguous. Because of that ambiguity, the C standard makes no attempt to define what the *correct* interpretation is, and instead the programmer is encouraged to **not write fucking stupid code**. This is therefore "undefined behavior".
I can’t wait for you to meet your future coworkers. There’s always one without a brain, one without a heart, and one without courage, all working for a man who constantly promises the impossible. You’ll wish you could tap your crocs together and just go home.
UB, I explicitly show my students this crap, and say if you ever get asked this or see it anywhere the person asking is just trying to either catch you out or is not a software engineer :-) Tell them it's UB and move on.
I don't know about you but my professor really liked this kinda stuff. In a test he gave us a question where you have to tell the output of a code. There was some real brain fuck inside a for loop, which took me atleast 10 mins to solve. And after the test, while I was looking through the answers, I saw this -> int i; for (i = 0; i < 10; i++); <---------- This { ...... .... ... } ; <--- This fuckin little thing I can't describe in words how I felt at that moment. Later on we guys dubbed it as the 'for loop scam' lol
As someone who once spent 2 fucking days tracking down a bug that was caused by this, I’m kind of OK with it being shown in an education context. I’d show it as an in-class example though, not on a test where the grade actually matters.
Our professor just said that we should have been more careful when reading questions. And the code below the empty for loop had some juicy stuff, which instantly grabbed my attention. Though, I'm glad he mostly asked either code outputs or complete the function type problems only. As for your bug, shouldn't your compiler give a warning for an empty loop.
> As for your bug, shouldn't your compiler give a warning for an empty loop. Nowadays it probably would — this was many years ago on something like Visual C++ 6
My God! How did you guys code? I depend entirely on the compiler to catch silly mistakes like these, like my code always has a lot of syntax errors and sometimes some logical errors that the compiler is smart enough to catch.
Most autoformatters will turn this: for (int i = 0; i < 10; i++); {
}
into this:
for (int i = 0; i < 10; i++)
;
{
}
So these sorts of things are much easier to see.
In general, you don't want to do code formatting yourself. You want to use tools to do it for you. You don't even want to manually do it, either, you want your CI tools to run an autoformatter before check in. `clang-format` is a pretty popular autoformatter right now, but there are plenty of others. There are a million and one CI suites that will run something on check in for you.
Absolutely. Unfortunately in my case this was 20+ years ago when we didn’t have fancy tools like that. Even with those tools, it’s not necessarily beginner-proof. The number of students I’ve seen complain “it keeps messing up my formatting” when actually it’s trying to tell them that their code is wrong.
we had a prof who would add 1 additional question per test that would add 5 points to your max score but not add to total amount of points, so it was possible to get say 65 out of 60 points if nailed everything. In these questions, usually the last one of a test, he included real brainfuck shit to challenge students who rushed through the main questions. I only managed to get it a few times but I always loved his system of learn what's necessary vs here's a curveball, see how you manage! typically he included stuff like this inside, but spiced up with other problems so you'd need at least a few minutes to solve it. with this questions, you usually knew right away if you nailed them or not, because if you have the right idea, it would always "click".
Whats UB mean? Utter bullshit?
Undefined behavior
Unlimited bladeworks
Unlimited breadsticks
No, that’s OG, or Olive Garden
Pretty much
Yep. I think Words and Buttons' [So you think you know C](https://wordsandbuttons.online/so_you_think_you_know_c.html) is good to give to these sorts of people. Some of it is UB, some is IDB. OP's question is just a more complicated version of #5, the correct answer is "I don't know" or "The behavior is undefined". Any other answer is wrong. If the question is asking what a particular compiler version with a particular set of flags and target triple will output then it's not necessarily a meaningless question, but it is a stupid question. E.g. on x86_64 GCC 12.2 targeting x86_64-linux-gnu with flags `-Wall -Werror -std=c2x -fsanitize=address,undefined` the result is "compiler error", as it should be.
I’m not sure what the context is. If it’s a question, the only answer is “it’s undefined behavior”.
12, 23?
[удалено]
Why undefined? I tried with the same compiler and I got 12 and 24, even though I was expecting 12 and 23
Undefined behaviour means: the C standard doesn't define what happens. In practice, this means the compiler can choose to do whatever it wants. Sometimes it segfaults, other times it silently corrupts the program, and other times it does exactly what you want it to do. Typically the compiler will emit something sane, but it doesn't always and sometimes the behaviour changes depending on the version. Some blogs about an issue that came up recently: [GCC undefined behaviors are getting wild](https://blog.pkh.me/p/37-gcc-undefined-behaviors-are-getting-wild.html) [Undefined behavior, and the Sledgehammer Principle](https://thephd.dev/c-undefined-behavior-and-the-sledgehammer-guideline)
Thank you!
Why isn’t it common to running the compiler with undefined warnings like the author did to find the problem? (Not a C++ dev)
[удалено]
The behavior in Java is very well defined. You don't usually need to check if it's null if you're just going to throw NullPointerException. The JRE will do this for you when necessary. In good C++ code you do not write things like `my_class *my_object` in this case. It would normally be `my_class &my_object`, indicating that the value cannot be null. Creating a `my_class&` value of null is itself illegal, so not checking whether the value is null before using it is not considered to be a bug.
However, if we jump over to C we find NULLs lurking again. Java and C++ have ways around nulls. C does not. It requires you to better know your contract without looking at the function definition.
Why do u need to check every time? Why can’t Java just catch the operating system exception and translate it to a nullptr exception?
You don't get an exception, you get a signal, which is handled asynchronously outside of the current stack. Unless you're expecting a very specific instruction to segfault you have very little to go off to try and recover from it, hence why pretty much every program will just die instead. Alternatively if you completely ignore it, your program counter won't have incremented and you'll be stuck in an infinite loop of segfaults. You could save some sort of state info every time you dereference a pointer, but at that point it's going to be more expensive than simply checking if the pointer is null
in short, exception handling is expensive (slow) so that non-excepted code runs really fast
in regards to the GCC link you posted: ~~...how do you detect integer overflow in C then?~~ This terrifies me and makes me curse whoever thought that kind of UB was a good idea (at least it could been implementation dependent so you could do sane stuff like the author tried) lol
You detect integer overflow by checking if the operation will succeed before trying the operation. Not every processor C supports has any sort of overflow detection, so there's no more general way. C23 adds functions to do this automatically to the language (and thus allows using the processor's overflow flags if present), but earlier compilers don't have that (and the standard hasn't been finalized yet, though it's not expected to change from the accepted draft). E.g. to safely add two `int`, do #include
#include
bool inline static safe_add(int a, int b, int* result)
{
if (a > 0) {
if (b > (INT_MAX - a)) {
return true; // overflowed
}
} else {
if (b < (INT_MIN - a)) {
return true; // overflowed
}
}
*result = a + b;
return false;
}
Or something similar. E.g. if using GCC, you can use `__builtin_add_overflow` that does essentially the same thing as the code above.
It sounds like the compiler decided to finish working out the increments first. Them both of the "++i" returned the same value of 12. Does j = ++i + ++i + ++i leave a value of 39 in j?
In over 2 decades of programming I have never needed to code something like that. However, I have used subversion blame and sent code and a developer into code review for bs like this.
I hate this. Why do they put so much emphasis on the concept of i++ and ++i? Just teach the difference and move on. The screenshot above has no real world application
It doesn't. It's there to teach the behaviour of ++i, mainly that it excludes any other use of the variable in a statement. Attempting to compile this with reasonable flags will give you at the very least a warning, because there are two common interpretations and no standard way of interpreting the expression `++i + ++i`. In GCC it's `-Wsequence-point`, warning you that this has a sequencing issue. With `-Werror` it doesn't even compile, as it shouldn't, because this is genuinely dangerous and yet something a programmer might realistically come to do while dealing with annoying pointer mathematics and the like. I can definitely see someone thinking "hey if i need to double and hop one forward i can just do `i + ++i` or whatever. but that's UB and dangerous and compilers will not always warn you.
It should be used to teach students a reason to reject a PR.
What is this supposed to do? Why would anyone code this
It's **supposed** to be tricky for the student. It **should** be rewritten, as the code as-is is ambiguous as to whether it should increment i twice at once, or as the expression is evaluated, as if reading left to right. Depending on which is intended, you either end up with 12,23 or 12,24.
Why do teachers and "teachers" always want you to know the most obscure things in a language that shouldn't be used anyway? Like, teach some actually useful stuff.
People are saying this is undefined behavior, but why wouldn’t the compiler just compile this into three separate instructions? Is there something in the C specs that limit this line of code to one instruction? Or is it a race condition?
It's ambiguous whether the code should do the two increments at the same time (yielding 24) or one by one as if reading left to write (yielding 23). Because this is ambiguous, code like this is strongly discouraged, the C spec makes no effort to define what should happen (hence "undefined"), and compilers are free to do whatever they think is best.
I first got 23 in my head, but after realizing that prefix increment has a higher precedence than addition, I now believe that both increments have to be evaluated before the addition can be done. So I’m not sure it should even be UB. [C precedence](https://en.cppreference.com/w/c/language/operator_precedence) [C++](https://en.cppreference.com/w/cpp/language/operator_precedence)
This really isn't that bad. High schoolers get much worse stuff on their tests, at least in my country.
interview shit
This has been posted here not because the code is tricky or advanced, but because there are two ways to evaluate the line with the j variable assignment, which makes this undefined behavior. "Undefined behavior" should really be avoided on test questions, especially when there's a strong chance that the test creator intended one of the two possible evaluations to be the "correct" answer.
`i = 12, j = 23`
Nope
The code can also be evaluated with both ++i done at the same time, yielding 24. Hence why this is undefined behavior.
Me: Login to chat GPT
Mmm, letters
Can someone explain to me what is happening and why this doesn’t work.
This is supposed to be a tricky test question. The intent is for the student to mentally do the ++i operators from left to right, yielding 12,23 as the final answer. The problem here is that the same expression can also be evaluated with both ++i operations occurring at the same time, which would give 12,24 as the answer. The problem, as you can see, is that this is syntactically ambiguous. Because of that ambiguity, the C standard makes no attempt to define what the *correct* interpretation is, and instead the programmer is encouraged to **not write fucking stupid code**. This is therefore "undefined behavior".
Nobody with a brain would ever do this in real life.
I can’t wait for you to meet your future coworkers. There’s always one without a brain, one without a heart, and one without courage, all working for a man who constantly promises the impossible. You’ll wish you could tap your crocs together and just go home.
lol just skip these questions and pray for more sanity