总结一些遇到的C语言的“奇妙”例子,虽然应用上没什么卵用,但是可以考察对细节的理解
i++和++i谁快
结论
++i更快:
i++相比++i,多一步将自加的i赋值给寄存器的指令,相当于创建临时变量。
虽然在这里只相差一条指令,但是如果i为类对象,那么i++多出的创建临时变量的指令会更多
a = a++ 和 a = ++a 中,a自增了吗?
结论
a = a++
是先压栈a,然后自增,最后出栈a。所以a自增了,但是结果放在中间寄存器没有赋值回来,所以可以说没自增😂a = ++a
是先自增,然后压栈,最后出栈。所以a的确自增了。
fork后进程共享文件描述符吗?
结论
fork后进程共享文件描述符,同时也共享文件表项(意味着共享文件位移量等等)
各种类型数值间的转换
从有符号数转换
从无符号数转换
总结
高转低,先截断高位,再根据目标有无符号解释值
低转高,先根据源有无符号扩展高位,再根据目标有无符号解释值
相同位宽,只根据目标有无符号解释值
你真的了解typedef吗?
同时存在同名函数和变量?
通常我们会使用typedef void (*foo_t)(void);
来定义一个函数指针的类型(或者说别名),但你有没有想过如果去掉那个解引用符号*
,会发生什么?
奇怪的是,如下的代码能正常工作,foo_t foo;
表现得好像定义一个全局变量一样:
typedef void (foo_t)(void);
foo_t foo;
int main(){
foo();
return 0;
}
void foo(void){
...
}
原理其实很好理解,因为typedef
跟define
一样,本质上是一种别名(但不等同于字符替换),所以这里foo_t foo;
其实是void (foo)(void);
,也就是函数声明。
引人思考的是,变量的定义和函数的定义在C语言中,真的十分类似。这里又引申出来一种可能的用法:搭配X宏,在需要热重载的时候,使用typedef
定义函数指针;在需要静态链接的时候,使用typedef
定义函数声明。再通过测试宏在这两者之间切换。
Weird Parts of C you probably never heard of...
函数的参数被替换成什么了?
typedef char *T
void foo(const T arg){
...
}
如果是单纯的字符替换,那就是
const char *arg
又或者是
char * const arg
???
答案是2