# Undefined Behaviors
- [What are all the common undefined behaviours that a C++ programmer should know about? [closed]](https://stackoverflow.com/questions/367633/what-are-all-the-common-undefined-behaviours-that-a-c-programmer-should-know-a)
## 1
What is the output of the following program ?
```c
int main()
{
while(1){
if(printf("%d",printf("%d")))
break;
else
continue;
}
return 0;
}
```
:::spoiler Answer
- [printf](https://cplusplus.com/reference/cstdio/printf/)
- On success, the total number of characters written is returned.
- [Printf with no arguments explanation](https://stackoverflow.com/questions/27660586/printf-with-no-arguments-explanation)
- The inner printf returns number greater than zero, hence an arbitrary number is printed.
- While it is undefined behavior and anything can happen, on most systems you end up dumping the stack.
:::
## 2
What is the output of the following program ?
```c
int main()
{
int c=5;
printf("%d\n%d\n%d", c, c <<= 2, c >>= 2);
getchar();
}
```
:::spoiler Answer
Output: Compiler dependent
Undefined behavior, see [What is the order of evaluation for function arguments?](https://stackoverflow.com/questions/2934904/what-is-the-order-of-evaluation-for-function-arguments)
The evaluation order of parameters is not defined by the C standard and is dependent on compiler implementation.
- [What are all the common undefined behaviours that a C++ programmer should know about? [closed]](https://stackoverflow.com/questions/367633/what-are-all-the-common-undefined-behaviours-that-a-c-programmer-should-know-a)
:::
## 3
What is the output of the following program ?
```clike
#include <stdio.h>
int main(void) {
int a = 10, b = 20, c = 30;
printf("\n %d..%d..%d \n", a+b+c, (b = b*2), (c = c*2));
return 0;
}
```
:::spoiler Answer
Output: 110..40..60 (on my machine)(Undefined Behavior, compiler dependent)
- [What is the order of excecution of printf(..) parameters? [duplicate]](https://stackoverflow.com/questions/54560843/what-is-the-order-of-excecution-of-printf-parameters)
- [What are all the common undefined behaviours that a C++ programmer should know about? [closed]](https://stackoverflow.com/questions/367633/what-are-all-the-common-undefined-behaviours-that-a-c-programmer-should-know-a)
:::
## 4
What is the output of the following program ?
```clike
#include <stdio.h>
int main(void)
{
int i = 0;
i = i++ + ++i;
printf("%d\n", i); // 3
i = 1;
i = (i++);
printf("%d\n", i); // 2 Should be 1, no ?
volatile int u = 0;
u = u++ + ++u;
printf("%d\n", u); // 1
u = 1;
u = (u++);
printf("%d\n", u); // 2 Should also be one, no ?
register int v = 0;
v = v++ + ++v;
printf("%d\n", v); // 3 (Should be the same as u ?)
int w = 0;
printf("%d %d\n", ++w, w); // shouldn't this print 1 1
int x[2] = { 5, 8 }, y = 0;
x[y] = y ++;
printf("%d %d\n", x[0], x[1]); // shouldn't this print 0 8? or 5 0?
}
```
:::spoiler Answer
關鍵在於:不論是 `i = i++` 或是 `i = ++i`,都沒有規定說 assign 給左邊的 `i` 的順序是要在加完之後還是之前。
Output: Undefined Behavior, compiler dependent, could be anything
- [Why are these constructs using pre and post-increment undefined behavior?](https://stackoverflow.com/questions/949433/why-are-these-constructs-using-pre-and-post-increment-undefined-behavior)
- [What are all the common undefined behaviours that a C++ programmer should know about? [closed]](https://stackoverflow.com/questions/367633/what-are-all-the-common-undefined-behaviours-that-a-c-programmer-should-know-a)
:::
## 5
What is the output of the following program ?
```clike
#include<stdio.h>
int main(void)
{
int a = 1;
int b = 0;
b = ++a + ++a;
printf("%d %d",a,b);
getchar();
return 0;
}
```
:::spoiler Answer
關鍵在於:不論是 `i = i++` 或是 `i = ++i`,都沒有規定說 assign 給左邊的 `i` 的順序是要在加完之後還是之前。
Output: Undefined Behavior, compiler dependent, could be anything
- [Why are these constructs using pre and post-increment undefined behavior?](https://stackoverflow.com/questions/949433/why-are-these-constructs-using-pre-and-post-increment-undefined-behavior)
- [What are all the common undefined behaviours that a C++ programmer should know about? [closed]](https://stackoverflow.com/questions/367633/what-are-all-the-common-undefined-behaviours-that-a-c-programmer-should-know-a)
:::
## 6
What is the output of the following program?
```clike!
#include <stdio.h>
int main(void)
{
int a;
int b = 1;
int x[5] = { 1, 2, 3, 4, 5 };
a = 5 * 4 + x[--b] - (9 / b);
printf("%d", a);
return 0;
}
```
:::spoiler Answer
Output: 21(on my machine), Undefined behavior, could be anything, may be `9 / 0` which cause an devide by zero error.
Explaination:
```console!
test.c:6:17: warning: unsequenced modification and access to 'b' [-Wunsequenced]
```
similar case:
```clike!
#include <stdio.h>
int main(void)
{
int a;
int b = 1;
int x[5] = { 1, 2, 3, 4, 5 };
a = 5 * 4 + x[b++] - (9 / b);
printf("%d", a);
return 0;
}
```
Output: 18(on my machine), Undefined behavior, could be anything.
Explaination:
```console!
test.c:6:17: warning: unsequenced modification and access to 'b' [-Wunsequenced]
```
:::
## 7
What is the output of the following program?
```clike!
#include <stdio.h>
int main(void)
{
int a;
int i = 1;
int b = 10 * i + sizeof(--i) + 4 - 10 / i;
printf("%d", b);
return 0;
}
```
:::spoiler Answer
Output: 8
Explaination: Undefined behavior, could be anything.
我猜想 compiler 並不會真的去對 i 減一,因為 sizeof an int 都是一樣的,因此在這個例子當中, i 的值從頭到尾都是 1。
```console!
test.c:5:26: warning: expression with side effects has no effect in an unevaluated context [-Wunevaluated-expression]
```
實際看個例子的 assembly code:
先看有做減法的:
```clike!
#include <stdio.h>
int main(void)
{
int a = 2;
int b = 3;
int c = a - b;
return 0;
}
```
注意 `subu $2,$3,$2` 這行!
```assembly!
$LFB0 = .
main:
addiu $sp,$sp,-32
sw $fp,28($sp)
move $fp,$sp
li $2,2 # 0x2
sw $2,8($fp)
li $2,3 # 0x3
sw $2,12($fp)
lw $3,8($fp)
lw $2,12($fp)
nop
subu $2,$3,$2
sw $2,16($fp)
move $2,$0
move $sp,$fp
lw $fp,28($sp)
addiu $sp,$sp,32
jr $31
nop
```
```clike!
#include <stdio.h>
int main(void)
{
int i = 1;
int b = 10 * i + sizeof(--i) + i;
printf("%d", b);
return 0;
}
```
對應的 mips gcc 13.2.0 的 assembly code 會是:
```assembly!
$LC0:
.ascii "%d\000"
$LFB0 = .
main:
addiu $sp,$sp,-40
sw $31,36($sp)
sw $fp,32($sp)
move $fp,$sp
li $2,1 # 0x1
sw $2,24($fp)
lw $3,24($fp)
nop
move $2,$3
sll $2,$2,2
addu $2,$2,$3
sll $2,$2,1
move $3,$2
lw $2,24($fp)
nop
addu $2,$3,$2
addiu $2,$2,4
sw $2,28($fp)
lw $5,28($fp)
lui $2,%hi($LC0)
addiu $4,$2,%lo($LC0)
jal printf
nop
move $2,$0
move $sp,$fp
lw $31,36($sp)
lw $fp,32($sp)
addiu $sp,$sp,40
jr $31
nop
```
可看到並沒有出現任何的 `subu` 指令,因此推斷 `i` 的值從頭到尾都沒有被 decrement。
:::
## 8
```clike
#include <stdio.h>
int main()
{
int i;
i = 10;
printf("i : %d\n",i);
printf("sizeof(i++) is: %d\n",sizeof(i++));
printf("i : %d\n",i);
return 0;
}
```
:::spoiler Answer
Output:
i : 10
sizeof(i++) is: 4
i : 10
Explaination:
同 7., compiler 並不會真的執行 `i++`,因為 `sizeof(i++)` 只需要知道其大小就行了。
sizeof 不是一個函數,是一個運算子,其求i++ 的類型的 size,這是一件可以在程式執行前(編譯時)完全的事情,所以,sizeof(i++) 直接就被4給取代了,在執行階段也就不會有了 i++ 這個表示式
可觀察組語中的第十五行的 `mov esi, 4` 就是代表 sizeof(i++) 被4給取代了。
```assembly=
.LC0:
.string "i : %d\n"
.LC1:
.string "sizeof(i++) is: %d\n"
main:
push rbp
mov rbp, rsp
sub rsp, 16
mov DWORD PTR [rbp-4], 10
mov eax, DWORD PTR [rbp-4]
mov esi, eax
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
mov esi, 4
mov edi, OFFSET FLAT:.LC1
mov eax, 0
call printf
mov eax, DWORD PTR [rbp-4]
mov esi, eax
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
mov eax, 0
leave
ret
```
:::