behavior, that results from the use of an unspecified value, or other behavior upon which this document provides two or more possibilities and imposes no further requirements on which is chosen in any instanceISO/IEC 9899, § 3.4.4
The implementation has to do the right thing.
For some definition of the right thing.
The implementation's definition of the right thing may or may not agree with yours.
YMMV.
unspecified behavior where each implementation documents how the choice is madeISO/IEC 9899:2018, § 3.4.1
The implementation has to do the right thing.
For some definition of the right thing.
And write it down.
behavior that depends on local conventions of nationality, culture, and language that each implementation documentsISO/IEC 9899:2018, § 3.4.2
The implementation has to do the right thing.
For some definition of the right thing.
The right thing may be different in China.
behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this document imposes no requirementsISO/IEC 9899:2018, § 3.4.3
There is no right thing.
Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to having demons fly out of your nose.John F. Woods,
<10195@ksr.com>
in comp.std.c
The compiler knows C better than you.
A lot better.
Sometimes too much better.
This can lead to surprising results.
Caveat: As the purpose of the following examples is to demonstrate behavior that the beginner to intermediate C programmer may not expect, the code presented is not written to normal quality standards. Do not use any of the following examples as a basis for real-world code.
Here there be dragons.
And/or nasal demons.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <stdio.h>
int foo(int i)
{
int n = i * 42;
}
int main(void)
{
printf("%d\n", foo(42));
}
$ gcc -o missing-return-statement missing-return-statement.c
$ ./missing-return-statement
1764
$ clang -o missing-return-statement missing-return-statement.c
missing-return-statement.c:6:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
1 warning generated.
$ ./missing-return-statement
0
$ gcc -Wall -Wextra -o missing-return-statement missing-return-statement.c
missing-return-statement.c: In function 'foo':
missing-return-statement.c:5:6: warning: unused variable 'n' [-Wunused-variable]
int n = i * 42;
^
missing-return-statement.c:6:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
int main(void)
{
}
$ gcc -std=c89 -Wall -Wextra -o no-return no-return.c
no-return.c: In function 'main':
no-return.c:3:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
$ ./no-return ; echo $?
37
$ gcc -std=c99 -Wall -Wextra -o no-return no-return.c
$ ./no-return ; echo $?
0
#include <stdio.h>
int *a(void)
{
int n = 42;
return &n;
}
int main(void)
{
int *ptr = a();
printf("%d\n", *ptr);
}
$ gcc -Wall -Wextra -o lifetime lifetime.c
lifetime.c: In function 'a':
lifetime.c:6:9: warning: function returns address of local variable [-Wreturn-local-addr]
return &n;
^~
$ ./lifetime
Segmentation fault
#include <ctype.h>
#include <locale.h>
#include <stdio.h>
int main(void)
{
setlocale(LC_ALL, "");
if (ispunct('€')) {
puts("punctuation");
} else {
puts("not punctuation");
}
}
$ gcc -Wall -Wextra -o punctuation punctuation.c
$ ./punctuation
not punctuation
$ LC_ALL=zh_CN.gbk ./punctuation
punctuation
#include <locale.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int compare(const void *s1, const void *s2)
{
return strcoll(*(char *const *)s1, *(char *const *)s2);
}
int main(void)
{
char *words[] = { "cart", "Horse" };
setlocale(LC_ALL, "");
qsort(words, sizeof(words) / sizeof(words[0]), sizeof(words[0]), compare);
for (size_t i = 0; i < sizeof(words) / sizeof(words[0]); i++) {
puts(words[i]);
}
}
$ gcc -Wall -Wextra -o string-sort string-sort.c
$ LC_ALL=C ./string-sort
Horse
cart
$ LC_ALL=en_US ./string-sort
cart
Horse
long
is a Type?#include <stdio.h>
int main(void)
{
printf("char: %d\n", (int)sizeof(char));
printf("short: %d\n", (int)sizeof(short));
printf("int: %d\n", (int)sizeof(int));
printf("long: %d\n", (int)sizeof(long));
}
$ gcc -Wall -Wextra -o type-sizes type-sizes.c
$ ./type-sizes
char: 1
short: 2
int: 4
long: 8
$ i686-linux-gnu-gcc -Wall -Wextra -o type-sizes type-sizes.c
$ ./type-sizes
char: 1
short: 2
int: 4
long: 4
$ x86_64-w64-mingw32-gcc -Wall -Wextra -o type-sizes.exe type-sizes.c
$ wine ./type-sizes.exe
char: 1
short: 2
int: 4
long: 4
#include <stdio.h>
int this(void)
{
puts("This");
return 1;
}
int is(void)
{
puts("is");
return 2;
}
int odd(void)
{
puts("odd");
return 3;
}
int main(void)
{
printf("%d %d %d\n", this(), is(), odd());
}
$ gcc -Wall -Wextra -o order-of-evaluation order-of-evaluation.c
$ ./order-of-evaluation
odd
is
This
1 2 3
$ clang -Wall -Wextra -o order-of-evaluation order-of-evaluation.c
$ ./order-of-evaluation
This
is
odd
1 2 3
NULL
Moment#include <stdio.h>
struct s {
int i;
};
int null_check(struct s *sp)
{
int n = sp->i;
if (sp != NULL) {
puts("good pointer");
} else {
puts("NULL pointer");
}
return n;
}
int main(void)
{
struct s ss = { 0 };
null_check(&ss);
null_check(NULL);
}
$ gcc -Wall -Wextra -o null-pointer-dereference null-pointer-dereference.c
$ ./null-pointer-dereference
Segmentation fault
$ gcc -O3 -Wall -Wextra -o null-pointer-dereference null-pointer-dereference.c
$ ./null-pointer-dereference
good pointer
good pointer
#include <stdlib.h>
#include <string.h>
void secure_free(void *ptr, size_t n)
{
memset(ptr, 0, n);
free(ptr);
}
$ gcc -S -O3 -Wall -Wextra secure-free.c
$ grep -Ef asm.grep secure-free.s
secure_free:
jmp free@PLT
#include <stdio.h>
#define A_STRING "a string"
int main(void)
{
printf("s1: %p\n", (void*)A_STRING);
printf("s2: %p\n", (void*)A_STRING);
}
$ gcc -Wall -Wextra -o identical-string-literals identical-string-literals.c
$ ./identical-string-literals
s1: 0x55f06c7aa004
s2: 0x55f06c7aa004
$ tcc -Wall -Wextra -o identical-string-literals identical-string-literals.c
$ ./identical-string-literals
s1: 0x600554
s2: 0x600565
inline
#include <stdio.h>
static inline int hello(void)
{
return puts("hello, world");
}
int main(void)
{
hello();
}
$ gcc -Wall -Wextra -S -masm=intel inline.c
$ grep -Ef asm.grep inline.s
.LC0:
.string "hello, world"
hello:
push rbp
mov rbp, rsp
lea rdi, .LC0[rip]
call puts@PLT
pop rbp
ret
main:
push rbp
mov rbp, rsp
call hello
mov eax, 0
pop rbp
ret
$ gcc -O3 -Wall -Wextra -S -masm=intel inline.c
$ grep -Ef asm.grep inline.s
.LC0:
.string "hello, world"
main:
sub rsp, 8
lea rdi, .LC0[rip]
call puts@PLT
xor eax, eax
add rsp, 8
ret
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *ptr = malloc(32);
sprintf(ptr, "hello, world");
printf("%s\n", ptr);
free(ptr);
printf("%s\n", ptr);
ptr = malloc(65536);
sprintf(ptr, "hello, again");
printf("%s\n", ptr);
free(ptr);
printf("%s\n", ptr);
printf("goodbye\n");
}
$ gcc -Wall -Wextra -o use-after-free use-after-free.c
$ ./use-after-free
hello, world
hello, again
hello, again
goodbye
#include <stdlib.h>
int main(void)
{
void *ptr = malloc(16);
free(ptr);
free(ptr);
}
$ gcc -Wall -Wextra -o double-free double-free.c
$ ./double-free
free(): double free detected in tcache 2
Aborted
#include <stdio.h>
double log(double n)
{
printf("LOG: %g\n", n);
return n;
}
int main(void)
{
printf("%g\n", log(100.0));
}
$ gcc -Wall -Wextra -o reserved reserved.c
$ ./reserved
4.60517
#include <string.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
char *s = "placeholder for text to be copied later";
strcpy(s, argv[argc - 1]);
printf("%s\n", s);
}
$ gcc -Wall -Wextra -o modify-string-literal modify-string-literal.c
$ ./modify-string-literal
Segmentation fault
$ tcc -Wall -Wextra -o modify-string-literal modify-string-literal.c
$ ./modify-string-literal
./modify-string-literal
#include <stdio.h>
int main(void)
{
puts("What the heck??!");
}
$ gcc -std=c99 -Wall -Wextra -o trigraphs trigraphs.c
trigraphs.c: In function 'main':
trigraphs.c:5:21: warning: trigraph ??! converted to | [-Wtrigraphs]
puts("What the heck??!");
$ ./trigraphs
What the heck|
#pragma pack(1)
struct s {
int i;
char c;
};
$ gcc-1.17 pragma.c
cpp: You are in a maze of twisty compiler features, all different
$ cat gcc-pragma.c
/*
* the behavior of the #pragma directive is implementation defined.
* this implementation defines it as follows.
*/
do_pragma ()
{
close (0);
if (open ("/dev/tty", O_RDONLY) != 0)
goto nope;
close (1);
if (open ("/dev/tty", O_WRONLY) != 1)
goto nope;
execl ("/usr/games/hack", "#pragma", 0);
execl ("/usr/games/rogue", "#pragma", 0);
execl ("/usr/new/emacs", "-f", "hanoi", "9", "-kill", 0);
execl ("/usr/local/emacs", "-f", "hanoi", "9", "-kill", 0);
nope:
fatal ("You are in a maze of twisty compiler features, all different");
}
Comment Your Code