假设我想用C实现一个堆栈,它有一些不同的特性,比如当它以某种方式扩展时,决定如何重新分配,等等。比如说
typedef struct stack_int {
unsigned length;
unsigned allocated_length;
int *data_pointer;
} stack_int;
extern int stack_int_pop(stack *l);
但是在我的程序中,我想重用它,上面的int
被我自己的5个数据结构(我使用的一些结构)所取代。在所有情况下,我希望细节都是一样的。
问题:什么是“正确的”,或“惯用的C”,这样做的方式?
我可以想到各种各样的循环,比如制作一个通用堆栈,带有一个字段element_size
,但是在弹出和追加时,接口必然是丑陋的,而且据我所知也没有优化。我还发现了一个环形交叉口,
#define CONCAT_PRE(X, Y) X ## _ ## Y
#define CONCAT(X, Y) CONCAT_PRE(X, Y)
#define STACK_TYPE CONCAT(stack, STACK_ELEMENT_TYPE)
typedef struct STACK_TYPE {
unsigned length;
unsigned allocated_length;
STACK_ELEMENT_TYPE *data_pointer;
} STACK_TYPE;
STACK_ELEMENT_TYPE CONCAT(STACK_TYPE, pop)(stack *l) {
...
}
然后把它包括几次:
#define STACK_ELEMENT_TYPE int
#include "stack.c"
#define STACK_ELEMENT_TYPE my_struct
#include "stack.c"
但这似乎不像是一个“惯用的C”的方式,是非常混乱的人谁会读它,防止一个单一的头文件,等等等等.
3条答案
按热度按时间ryhaxcpt1#
我不得不承认,我不完全确定这里“最惯用”的事情是什么,但它肯定不会多次包含相同的头,请不要这样做,因为它可能会创建依赖循环,如果你使用比Editor.exe更好的IDE,你应该在.h文件中已经有一个包含保护。
然而,对于你的问题,我认为应该使用一个**(void *)**和一个由无符号字符组成的类型字段,至少这是Java对其数据结构进行分类的方式。此外,您只需定义与您自己的结构相关的数字。
当然,当你已经有了指向你提到的结构的指针时,这个方法特别有用。
如果您不热衷于使用这种方法(诚然有点笨拙),那么始终欢迎您创建并发存在的多个堆栈。
6ojccjat2#
类似这样的东西,使用
void*
传递指针,使用unsigned char *
进行地址计算。参见在https://ideone.com/4HRYn5上运行的代码(使用
xx
而不是intStack
,抱歉)neskvpey3#
下面是实现通用堆栈机制并使用宏示例化结构和方法的经典方法。它很容易扩展到其他标量或非标量类型,并允许在宏生成的代码不足的情况下实现变化。
stack.h中的声明:
stack.c中的定义:
可以使用宏来模拟参数化类型,并将
DEFINE_STACK_TYPE
声明替换为:但请注意,
stack(int)
只应用于定义typedef
类型,因为如果在多个上下文中使用,它将定义不同的类型,例如int stack_int_pop(stack(int) *s);