其实,C语言的“阴间特性”真不少,有些平时写单片机、普通业务代码未必碰得上,但一旦碰到,很容易怀疑人生。
举几个例子。
数组和指针,“像,但又不是一回事”
比如:
int a[10];很多场合里,a 会“退化”为指向首元素的指针:
int *p = a;但:
sizeof(a)得到的是整个数组的大小,而:
sizeof(p)得到的是指针大小,而函数参数:
void f(int a[10])这个 a 本质上其实还是:
void f(int *a)a[i] 居然等价于 i[a]因为:
a[i]本质定义成:
*(a + i)而加法:
a + i
和:
i + a
一样,所以:
i[a]居然也是合法C。例如:
int a[] = {10, 20, 30};printf("%d\n", 1[a]);不仅编译通过,还能输出:
20++*p、*p++、(*p)++ 完全不是一回事例如:
*p++不是“*p加一”,因为 ++ 后缀优先级比 * 高,所以实际上是:
*(p++)也就是:
先取 p 指向的值,然后 p 自己往后走。
而:
(*p)++才是:
指针不动,指向的那个变量加 1。
这是 C 指针表达式里最经典的劝退点之一。
char到底是有符号还是无符号,居然不一定
比如:
char c = 200;那么:
printf("%d", c);到底打印 200 还是负数?
答案是:
看实现。
普通 char 既可以等价于 signed char,也可以等价于 unsigned char。所以,工程中,如果你真的关心到底是:
-128 ~ 127
还是:
0 ~ 255
最好明确写:
signed char unsigned char
这在嵌入式里尤其容易踩坑。
有符号整数的溢出,竟是未定义行为
很多人觉得:
int x = INT_MAX;x++;应该自然变成 INT_MIN。
硬件上确实可能就是这么发生的,但 C 标准层面:
signed integer overflow 是 undefined behavior。
而 unsigned int 溢出则明确规定按模 2^n 回绕。所以,
UINT_MAX + 1才一定是 0。
这说明:
“CPU怎么做”和“C语言规定程序是什么意思”,不是一回事。i = i++这种东西比想象中更邪门
例如:
int i = 1;i = i++;很多初学者会争:
最后到底是 1 还是 2?
真正正确的反应应该是:
别这么写。
这类表达式很容易落入未定义行为或C标准的版本差异。
类似的:
printf("%d %d", i++, i++);也不要试图靠“从左往右”去脑补。
sizeof里的表达式,通常根本不会执行
例如:
int i = 10;printf("%zu\n", sizeof(i++));printf("%d\n", i);很多人第一眼会觉得 i 变成 11,可实际上通常还是:
10
因为 sizeof 大多数情况下只需要知道类型大小,并不会真正计算表达式。事实上,sizeof 并不是额外去“测量”一个变量占多少空间,而只是把编译器本来就掌握的类型信息暴露给程序员。
结构体里,居然会偷偷塞东西
例如:
struct A { char c; int x;};很多学生算:
1 + 4 = 5 字节
但实际上:
sizeof(struct A)很可能得到:
8
因为有:
内存对齐和padding。
再来一个:
struct { char a; double b; char c;};实际大小可能比想象的:
1 + 8 + 1 = 10
大很多,VS上测得24。这个在嵌入式、MCU中,与通信协议、CAN报文、Flash存储直接相关。
指针加 1,不一定地址只加 1
比如:
int *p;p++;如果 int 是 4 字节,那么地址通常加 4。
而:
double *p;p++;可能加 8。因此:
p + 1真正的意思是:
指向“下一个同类型对象”。
而不是:
数值地址简单 +1。函数指针的语法,确实像某种咒语
比如:
int (*f)(int, int);表示:
f 是一个指针,指向参数为两个 int、返回 int 的函数。
再升级:
int (*(*f[10])(void))(int);开始有邪门的气质了。
C 里甚至专门发展出:
clockwise/spiral rule
帮助人读这种声明。
更多精彩专栏,请戳珂学原理知识库。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.