哪种方法更适合在 C 中创建类型不可知的结构?

发布于 2024-11-29 10:34:23 字数 648 浏览 1 评论 0原文

我正在尝试编写一些通用结构。本质上,我需要的是 C++ 模板,但由于我是用 C 编写的,因此不考虑模板。目前我正在考虑两种方法来实现我想要的。

方法一:使用预处理器。像这样:

#define DEFINE_PAIR(T) typedef struct Pair_##T{ \
                           T x; \
                           T y; \
                        } Pair_##T

DEFINE_PAIR(int);

int main(){
   Pair_int p;
   return 0;
}

它的一个明显的缺点是您必须在使用该类型之前调用宏。可能还有更多的缺点,希望大家指出。

方法 2:只使用 void 指针,如下所示:

typedef struct Pair{
   void* x;
   void* y;
} Pair;

显然,这种方法不是类型安全的(我可以轻松地将一对字符串传递给需要一对双精度数的函数),而且执行释放的代码会变得更加混乱方法。

我想听听您对此的想法。这两种方法哪一个更好/更差,为什么?还有其他方法可以用来在 C 中编写通用结构吗?

谢谢。

I'm trying to write some generic structures. Essentially, what I need for my purpose is C++ templates, but since I'm writing in C, templates are out of consideration. Currently I'm considering 2 ways of achieving what I want.

Method 1: use the preprocessor. Like so:

#define DEFINE_PAIR(T) typedef struct Pair_##T{ \
                           T x; \
                           T y; \
                        } Pair_##T

DEFINE_PAIR(int);

int main(){
   Pair_int p;
   return 0;
}

An obvious downside to it is that you have to invoke the macro before using the type. Probably there are more disadvantages, which I hope you will point out.

Method 2: just use void-pointers, like so:

typedef struct Pair{
   void* x;
   void* y;
} Pair;

Obviously, this approach is not type safe (I could easily pass a pair of strings to a function expecting a pair of doubles), plus the code doing deallocation gets a lot messier with this approach.

I would like to hear your thoughts on this. Which of the two methods is better/worse and why? Is there any other method I could use to write generic structures in C?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

总攻大人 2024-12-06 10:34:23

如果您只计划使用原始数据类型,那么您最初的基于宏的解决方案似乎就足够了。但是,当您开始存储指向具有复杂结构的不透明数据类型的指针对时,这些数据类型旨在通过在函数之间传递指针来使用,例如:

complex_structure_type *object = complex_structure_type_init();
complex_structure_type_set_title(object, "Whatever");
complex_structure_type_free(object);

then 您必须

typedef complex_structure_type *complex_structure_type_ptr; 

这样做,以便

DEFINE_PAIR(complex_structure_type_ptr);

可以

Pair_complex_structure_type_ptr p;

然后

p.x = object;

但这只是一点点更多的工作,所以如果你觉得它对你有用,那就去做吧。您甚至可以将自己的预处理器放在一起,该预处理器会遍历代码,提取诸如 Pair_whatever 之类的内容,然后为 C 预处理器添加 DEFINE_PAIR(whatever)。不管怎样,你在这里提出的绝对是一个好主意。

就我个人而言,我只会使用 void 指针,而忘记强类型安全。 C 只是没有与其他语言相同类型的安全机制,并且您给自己忘记某些事情的机会越多,您意外创建的错误就越多。

祝你好运!

If you only plan on using primitive data types, then your original macro-based solution seems nifty enough. However, when you start storing pairs of pointers to opaque data types with complex structures underneath that are meant to be used by passing pointers between functions, such as:

complex_structure_type *object = complex_structure_type_init();
complex_structure_type_set_title(object, "Whatever");
complex_structure_type_free(object);

then you have to

typedef complex_structure_type *complex_structure_type_ptr; 

in order to

DEFINE_PAIR(complex_structure_type_ptr);

so you can

Pair_complex_structure_type_ptr p;

and then

p.x = object;

But that's only a little bit more work, so if you feel it works for you, go for it. You might even put together your own preprocessor that goes through the code, pulls out anything like Pair_whatever, and then adds DEFINE_PAIR(whatever) for the C preprocessor. Anyway, it's definitely a neat idea that you've presented here.

Personally, I would just use void pointers and forget about strong type safety. C just doesn't have the same type safety machinery as other languages, and the more opportunities you give yourself to forget something, the more bugs you'll accidentally create.

Good luck!

习惯成性 2024-12-06 10:34:23

注意到 C++ 中的模板提供了一种用于编写代码的语言,您可能会简单地考虑使用一些比 c 预处理器更强大的工具来生成代码。

现在,这确实为您的构建添加了另一个步骤,并使您的构建依赖于另一个收费(除非您愿意用 c 编写自己的生成器...),但它可能会提供您想要的灵活性和类型安全性。

Noting that templates in c++ provide a language for writing code, you might simple consider doing code generation with some tool more powerful than the c-preprocessor.

Now that does add another step to you build, and makes you build depend on another toll (unless you care to write your own generator in c...), but it may provide the flexibility and type-safety you desire.

花开雨落又逢春i 2024-12-06 10:34:23

这几乎是一样的,但更灵活一些:

#define PAIR_T(TYPE) \
    struct { \
        TYPE x; \
        TYPE y; \
    }


typedef PAIR_T(int) int_pair;
typedef PAIR_T(const char *) string_pair;

int main(void)
{
    int_pair p = {1, 1};
    string_pair sp = {"a", "b"};
}

This is almost the same, but it's a bit more nimble:

#define PAIR_T(TYPE) \
    struct { \
        TYPE x; \
        TYPE y; \
    }


typedef PAIR_T(int) int_pair;
typedef PAIR_T(const char *) string_pair;

int main(void)
{
    int_pair p = {1, 1};
    string_pair sp = {"a", "b"};
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文