@nrailgun
2017-11-01T22:01:44.000000Z
字数 1320
阅读 1295
程序设计
用 C 写内核的过程中,发现 list/array 等容器经常被使用。谨慎使用的 C++ 模板可以提高算法/容器代码的可复用性,但是 C 并不具备模板。
Linus 的容器实现非常奇特。不同于常规的“容器节点包含数据类型”的想法,Linux 采用了“数据类型保护容器节点”的设计。Linux 在数据类型中包含了 struct list_head
并通过 container_of
反向取出对象。
优点是不需要改动容器代码。
利用 gcc 拓展 __typeof__
实现宏。
#define SWAP(a, b) do { \
__typeof__(a) c = a; \
a = b; \
b = c; \
} while (0)
此处注意两个坑:
易用,但是如此展开会产生大量的代码,使得内核变得巨大;而且无法实现递归。
函数定义通过宏定义,函数名通过宏拼接实现。缺点是需要根据数据类型,手动额外定义类型实例;此外通常函数名也会比较臭长。
#define DEFINE_OPS(type) \
type type##_add(type a, type b) { \
return a + b; \
} \
type type##_sub(type a, type b) { \
return a - b; \
}
DEFINE_OPS(int);
DEFINE_OPS(float);
typedef char *char_ptr; // Tricks for pointer
DEFINE_OPS(char_ptr);
存在稍微优雅一点点的写法,不需要大量的 \
。
ops.c
#include "ops.h"
TYPE CONCAT(TYPE, _add)(TYPE a, TYPE b) {
return a + b;
}
TYPE CONCAT(TYPE, _sub)(TYPE a, TYPE b) {
return a - b;
}
concat.h
#ifndef CONCAT_H_94W6MHYQ
#define CONCAT_H_94W6MHYQ
#define CONCAT_I(A, B) A##B
#define CONCAT(A, B) CONCAT_I(A, B)
#endif /* end of include guard: CONCAT_H_94W6MHYQ */
ops.h
#include "concat.h"
TYPE CONCAT(TYPE, _add)(TYPE a, TYPE b);
TYPE CONCAT(TYPE, _sub)(TYPE a, TYPE b);
ops_inst.c
#define TYPE int
#include "ops.c"
#undef TYPE
#define TYPE float
#include "ops.c"
#undef TYPE
ops_inst.h
#ifndef OPS_INST_H_0BJAKZOW
#define OPS_INST_H_0BJAKZOW
#define TYPE int
#include "ops.h"
#undef TYPE
#define TYPE float
#include "ops.h"
#undef TYPE
#endif /* end of include guard: OPS_INST_H_0BJAKZOW */