Vic*_*tor 6 c c99 generic-programming
我试图通过为一个matrix类型提供一些预处理器定义来模拟C中的泛型.以下是摘录:
#define __matrix_struct(TYPE) \
struct { \
uint32_t sz; \
TYPE **ptr; \
}
#define __matrix_t(TYPE) matrix_ ## TYPE
#define __matrix_ptr_t(TYPE) __matrix_t(TYPE) *
#define __matrix_typedef(TYPE) typedef __matrix_struct(TYPE) __matrix_t(TYPE)
#define __matrix_allocator_name(TYPE) TYPE ## _matrix_alloc
#define __matrix_allocator(TYPE) \
__matrix_ptr_t(TYPE) __matrix_allocator_name(TYPE) (uint32_t sz) { \
uint32_t i; \
__matrix_ptr_t(TYPE) m = (__matrix_ptr_t(TYPE)) malloc(sizeof(__matrix_t(TYPE))); \
m->ptr = (TYPE **) malloc(sz * sizeof(TYPE *)); \
for (i = 0; i < sz; ++i) { \
m->ptr[i] = (TYPE *) calloc(sz, sizeof(TYPE)); \
} \
return m; \
}
#define __matrix_deallocator_name(TYPE) TYPE ## _matrix_free
#define __matrix_deallocator(TYPE) \
void __matrix_deallocator_name(TYPE) (__matrix_ptr_t(TYPE) m) { \
uint32_t i; \
for (i = 0; i < m->sz; i++) { \
free(m->ptr[i]); \
} \
free(m->ptr); \
free(m); \
}
#define matrix_alloc_ptr(TYPE, SIZE) __matrix_allocator_name(TYPE) (SIZE)
#define matrix_dealloc_ptr(TYPE, PTR_NAME) __matrix_deallocator_name(TYPE) (PTR_NAME)
Run Code Online (Sandbox Code Playgroud)
在另一个文件中byte_matrix.h,我试图定义一个uint8_t值矩阵,如下所示:
#include "matrix.h"
typedef uint8_t byte;
__matrix_typedef(byte);
__matrix_allocator(byte)
__matrix_deallocator(byte)
Run Code Online (Sandbox Code Playgroud)
当我尝试编译时,我收到以下错误:
CMakeFiles/tictac.dir/game/board.c.o: In function `byte_matrix_alloc':
/home/victor/dev/pc/tictac/game/../matrix/byte_matrix.h:13: multiple definition of `byte_matrix_alloc'
CMakeFiles/tictac.dir/main.c.o:/home/victor/dev/pc/tictac/game/../matrix/byte_matrix.h:13: first defined here
CMakeFiles/tictac.dir/game/board.c.o: In function `byte_matrix_free':
/home/victor/dev/pc/tictac/game/../matrix/byte_matrix.h:14: multiple definition of `byte_matrix_free'
CMakeFiles/tictac.dir/main.c.o:/home/victor/dev/pc/tictac/game/../matrix/byte_matrix.h:14: first defined here
Run Code Online (Sandbox Code Playgroud)
我无法理解为什么它会指向同一行并且抱怨该定义,因为我写的每个标题都包括警卫.你能解释一下吗?如果您知道更好的方法来解决我的问题,请告诉我.谢谢.
-std=c99如果在这种情况下重要,我还需要编译.
一个快速修复方法是添加static到您的函数定义中。这将在引用标头的每个编译单元中创建这些函数的静态副本。如果您希望每次都内联函数,那么这就是正确的方法。
另一种方法是将函数声明保留在 .h 文件中,并将实际定义保留在单个 .c 文件中。这种方法将避免重复,并且编译器不会内联它们(除非您的链接器支持链接时间优化)。
原因是您将此头文件包含在多个编译单元中。预处理器完成所有文本替换后,您最终会在 .c 文件中得到实际的单独函数定义。如果您没有指定您希望它们是static,则默认情况下它们是extern,这意味着如果代码的其他部分想要调用它们,编译器现在不知道如何区分它们。
这就是您每次创建头文件时基本上要做的事情:创建一个声明列表,这些声明将包含在许多编译单元中,但单个 .c 文件中始终有一个外部定义。