4.8-引用传递的骗局

在以前的 C 教科书上,一直教导我们,C 语言函数有两种传递参数的方式:值传递和引用传递。但是,今天在看 c-faq 的 4.11 的时候,才了解到真相。其实严格意义上来讲,C 语言只有值传递,但是编译器可以模拟引用传递,但本质上,还是值传递。
举个例子:

1
2
3
4
void f(int *p);

int i;
f(&i);

阅读全文

2.14, 2.15-offset 和 struct 成员异类访问

今天在看 c-faq 的时候,碰到一个很奇怪的写法:

1
*(int *)((char *)structp + offsetf) = value;

其中 offsetf 是由 offsetof 宏计算出来的。这个表达式是用来不通过名字来引用结构体成员,而是通过偏移量来引用这个成员。感觉很有意思,那咱就深究一下吧!

首先,咱看一下 offsetof 这个 ANSI C 定义的宏,它是专门用来计算 struct 或者 union 类型成员的偏移量的。它的定义在 stddef.h 这个头文件中,用法很简单,给个例子就明白了:

阅读全文

2.10-designated initializer

在阅读 kernel 源码的时候,经常会碰到类似的代码:

1
2
3
4
struct test p= {
.initial=3;
.ptr=xx;
};

好像有点陌生吧,这是什么写法?
这其实是 C99 新增的内容,叫做 designated initializer,暂且翻译为”标识初始器“吧!
在 C90 之前,当你初始化一个数组,结构体或者联合体 (union) 的时候,你必须按照之前定义的顺序来初始化,且中间还不能跳跃。
这在 C99 之后,就已经打破了。

阅读全文