没有人类了之C语言冷知识
前言
明天就要科协笔试了,为了避免学长学姐出一些奇奇怪怪的 C 语言内容,所以我学了一些奇奇怪怪的东西。
冷知识
左移运算
C 的标准是 类型比特数 $\le$ 移位数 是未定义行为,所以以下表达式的结果是未定义的。
1 | 1u << 32 |
另外,有符号负数的左移是未定义行为,不能说以下表达式保证得到 -2。
1 | -1 << 1 |
逗号运算符
1 | int main() { |
逗号运算符的运算规则是先算前边的,然后把最后一个的结果当成这个表达式的结果返回。
二级指针不允许隐式转换
会存在安全漏洞,所以以下代码是不合法的:
1 | char *p=NULL; |
但是一级指针是可以的。
结构体的对齐规则
每个成员按自身大小对齐,结构体整体按照最大成员大小对齐!
1 | struct S{ char c;int x;char d;}; |
三目运算符的隐式类型转换
1 | int flag=1; |
原因是这个表达式有两个分支,一个是 int 一个是 unsigned int ,这个时候会自动转化为 unsigned int,所以 flag 变成了一个极大值,那显然就不小于 0 了。
浮点数的存储方式
这里以 float 为例,它的存储逻辑是:1 位符号位,8 位数字位,23 位尾数位
VLA
可变长数组,定义大概如下,是个可变长度的,在 C17 可选的特性:
1 | int n=3; |
创建后是锁死的,改变 n 的值不会导致数组的大小被改变。
VLA 类型还有新的数据类型,如下:
1 | int[n] |
这表示一个大小为 n 的 VLA,它的sizeof 结果是 $4n$。
C 标准存储期
分为以下四种:
- 自动存储期:普通的函数变量
- 静态存储期:静态变量
- 分配存储期:malloc
- 线程存储期(考试不考!)
逻辑与和逻辑或的短路现象
1 | int x=0; |
这个代码看似除以 0 了,但是因为 x 本身就是 0,所以已经确定这个表达式会返回 0 了,就短路掉了,后面的内容不会执行。
逻辑或运算也同理。
尾后指针
对于一个数组 T a[4] 来说:
a+0到a+3指向数组元素,可以解引用和读写。a+4是合法指针,标准允许定义它、比较它、做差、当结束迭代器使用,但是不能解引用。
a+5 以后的指针直接就是未定义的野指针。
sizeof 相关
1 | int a[4]; |







