@nrailgun
        
        2017-11-01T14:01:44.000000Z
        字数 1320
        阅读 1574
    程序设计
用 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 pointerDEFINE_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 */
