C/C++中常见的UB有：

• 整数溢出
• 序列点(Sequence Points)
• 违反了著名的Strict Aliasing规则

## 序列点

At certain specified points in the execution sequence called sequence points, all side effects of previous evaluations shall be complete and no side effects of subsequent evaluations shall have taken place.

Accessing a volatile object, modifying an object, modifying a file, or calling a function that does any of those operations are all side effects, which are changes in the state of the execution environment.

C99和C++2003都详细列出了序列点列表，一般只要我们不有意写很“紧凑”的代码，比如(a+=b)+=c或者a[i++]=i这种，多用分号标识一个完整表达式，则可以避免序列点问题导致的UB。曾经网易有面试题考过这种问题，个人感觉意义不大。

## strict aliasing

Strict aliasing同样也是为了编译器优化带来的规则，C99标准中规定了type-based aliasing rule（也被称作 ANSI aliasing rule），该规则说明一个指针只能被dereferenced到相同或相兼容类型的对象上，也就是说不同类型的指针不会引用同一块内存区域（即aliasing）。如果禁用了该规则，编译器访问内存需要更加谨慎。

Strict aliasing is an assumption, made by the C (or C++) compiler, that dereferencing pointers to objects of different types will never refer to the same memory location (i.e. alias eachother.)

Allows the compiler to assume the strictest aliasing rules applicable to the language being compiled. For C (and C++), this activates optimizations based on the type of expressions. In particular, an object of one type is assumed never to reside at the same address as an object of a different type, unless the types are almost the same. For example, an “unsigned int” can alias an “int”, but not a “void*” or a “double”. A character type may alias any other type.

uint32_t swap_words( uint32_t arg )
{
uint16_t* const sp = (uint16_t*)&arg; /* Error: undefined behavior */
uint16_t        hi = sp[0];
uint16_t        lo = sp[1];

sp[1] = hi;
sp[0] = lo;

return (arg);
}


uint32_t swap_words( uint32_t arg )
{
char* const sp = (char*)&arg;
uint16_t tmp;
memcpy(&tmp, sp, sizeof(uint16_t));
memcpy(sp + sizeof(uint16_t), sp, sizeof(uint16_t));
memcpy(sp, sp + sizeof(uint16_t), sizeof(uint16_t));

return (arg);
}