[关闭]
@nrailgun 2017-11-01T22:01:44.000000Z 字数 1320 阅读 1295

C:创建可复用的模板函数

程序设计


用 C 写内核的过程中,发现 list/array 等容器经常被使用。谨慎使用的 C++ 模板可以提高算法/容器代码的可复用性,但是 C 并不具备模板。

ContainerOf 机制的容器

Linus 的容器实现非常奇特。不同于常规的“容器节点包含数据类型”的想法,Linux 采用了“数据类型保护容器节点”的设计。Linux 在数据类型中包含了 struct list_head 并通过 container_of 反向取出对象。

优点是不需要改动容器代码。

宏函数

利用 gcc 拓展 __typeof__ 实现宏。

  1. #define SWAP(a, b) do { \
  2. __typeof__(a) c = a; \
  3. a = b; \
  4. b = c; \
  5. } while (0)

此处注意两个坑:

易用,但是如此展开会产生大量的代码,使得内核变得巨大;而且无法实现递归。

使用宏定义函数

函数定义通过宏定义,函数名通过宏拼接实现。缺点是需要根据数据类型,手动额外定义类型实例;此外通常函数名也会比较臭长。

  1. #define DEFINE_OPS(type) \
  2. type type##_add(type a, type b) { \
  3. return a + b; \
  4. } \
  5. type type##_sub(type a, type b) { \
  6. return a - b; \
  7. }
  8. DEFINE_OPS(int);
  9. DEFINE_OPS(float);
  10. typedef char *char_ptr; // Tricks for pointer
  11. DEFINE_OPS(char_ptr);

存在稍微优雅一点点的写法,不需要大量的 \

ops.c

  1. #include "ops.h"
  2. TYPE CONCAT(TYPE, _add)(TYPE a, TYPE b) {
  3. return a + b;
  4. }
  5. TYPE CONCAT(TYPE, _sub)(TYPE a, TYPE b) {
  6. return a - b;
  7. }

concat.h

  1. #ifndef CONCAT_H_94W6MHYQ
  2. #define CONCAT_H_94W6MHYQ
  3. #define CONCAT_I(A, B) A##B
  4. #define CONCAT(A, B) CONCAT_I(A, B)
  5. #endif /* end of include guard: CONCAT_H_94W6MHYQ */

ops.h

  1. #include "concat.h"
  2. TYPE CONCAT(TYPE, _add)(TYPE a, TYPE b);
  3. TYPE CONCAT(TYPE, _sub)(TYPE a, TYPE b);

ops_inst.c

  1. #define TYPE int
  2. #include "ops.c"
  3. #undef TYPE
  4. #define TYPE float
  5. #include "ops.c"
  6. #undef TYPE

ops_inst.h

  1. #ifndef OPS_INST_H_0BJAKZOW
  2. #define OPS_INST_H_0BJAKZOW
  3. #define TYPE int
  4. #include "ops.h"
  5. #undef TYPE
  6. #define TYPE float
  7. #include "ops.h"
  8. #undef TYPE
  9. #endif /* end of include guard: OPS_INST_H_0BJAKZOW */
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注