Cの暗いコーナーは見た目よりもずっと近く、些細なコード行でも未定義の動作をしていることを示したいと思います。
この記事は一連の質問として構成されています。 回答は白で書かれています。 すべての例は、個別のソースコードファイルです。
1。
int i; int i = 10;
Q: ? ( , , ? , , compound statement)
A: , . (tentative definition), , ( ).
2.
extern void bar(void); void foo(int *x) { int y = *x; /* (1) */ if(!x) /* (2) */ { return; /* (3) */ } bar(); return; }
Q: , bar() , x — ( ). ?
A: , . x — , (1) undefined behavior, : (1), return (2) (1). , , . (1) , x (2) (3) (dead code elimination). y *x volatile, .
.
3.
:
#define ZP_COUNT 10 void func_original(int *xp, int *yp, int *zp) { int i; for(i = 0; i < ZP_COUNT; i++) { *zp++ = *xp + *yp; } }
:
void func_optimized(int *xp, int *yp, int *zp) { int tmp = *xp + *yp; int i; for(i = 0; i < ZP_COUNT; i++) { *zp++ = tmp; } }
Q: , zp?
A: , yp == zp.
4.
double f(double x) { assert(x != 0.); return 1. / x; }
Q: inf ()? , IEEE 754 ( ). assert (NDEBUG ).
A: . x, , 1e-309.
5.
int my_strlen(const char *x) { int res = 0; while(*x) { res++; x++; } return res; }
Q: null-terminated . .
A: int : , int . size_t.
6.
#include <stdio.h> #include <string.h> int main() { const char *str = "hello"; size_t length = strlen(str); size_t i; for(i = length - 1; i >= 0; i--) { putchar(str[i]); } putchar('\n'); return 0; }
Q: . ?
A: size_t — . i , i >= 0 .
7.
#include <stdio.h> void f(int *i, long *l) { printf("1. v=%ld\n", *l); /* (1) */ *i = 11; /* (2) */ printf("2. v=%ld\n", *l); /* (3) */ } int main() { long a = 10; f((int *) &a, &a); printf("3. v=%ld\n", a); return 0; }
little-endian . :
1. v=10 2. v=11 3. v=11 1. v=10 2. v=10 3. v=11
Q: ?
A: undefined behavior, , (strict aliasing). (2) int, long . ( , .) (3) long, (1).
8.
#include <stdio.h> int main() { int array[] = { 0, 1, 2 }; printf("%d %d %d\n", 10, (5, array[1, 2]), 10); }
Q: ? undefined behavior, ?
A: , . , . : 10 2 10.
, (, f(a(), b())) : a(), b() .
9.
unsigned int add(unsigned int a, unsigned int b) { return a + b; }
Q: add(UINT_MAX, 1)?
A: , 2^(CHAR_BIT * sizeof(unsigned int)). 0.
10.
int add(int a, int b) { return a + b; }
Q: add(INT_MAX, 1)?
A: — undefined behavior.
11.
int neg(int a) { return -a; }
Q: undefined behavior? , ?
A: neg(INT_MIN). (. twos complement, ), INT_MIN , INT_MAX. -INT_MIN — undefined behavior.
12.
int div(int a, int b) { assert(b != 0); return a / b; }
Q: undefined behavior? , ?
A: , div(INT_MIN, -1) — . .
— Dmitri Gribenko <gribozavr@gmail.com>
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.