在C,通用容器或安全容器?

时间:2022-03-21 10:56:16

In C++ you can have both generic and type safe containers by using templates. However in C, if you want generic containers, you have to (afaik) use void*, which means you lose type safety. To have type safe containers, you would have to reimplement them for every type of data you want to hold.

在C ++中,您可以使用模板同时拥有通用容器和类型安全容器。但是在C中,如果你想要通用容器,你必须(afaik)使用void *,这意味着你失去了类型安全性。要拥有类型安全的容器,您必须为要保留的每种类型的数据重新实现它们。

Given that C follows a more the-programmer-knows-what-he's-doing philosophy than C++, what would be the more idiomatic thing to do in C: use generic containers with void*, or make custom containers for every type of data?

鉴于C遵循的是一个比C ++更多的程序员知道他所做的哲学,在C中做什么更惯用的事情:使用带有void *的通用容器,或者为每种类型的数据制作自定义容器?

4 个解决方案

#1


3  

I'd aim for generic containers:

我的目标是通用容器:

  1. Once you get used to it, you just think of void * is meaning the type of something when I don't care about it's type. It's like Object in Java -- where, for a long time, generic containers didn't have type safety either.

    一旦你习惯了它,你只要想到void *就意味着什么类型的东西,当我不关心它的类型。它就像Java中的Object - 很长一段时间,通用容器也没有类型安全性。

  2. You only have one place to make improvements.

    你只有一个地方可以改进。

  3. You don't get the type safety; but with repeated implementations of type safe containers, you run the risk of copy and paste errors. That can lead to errors, too.

    你没有得到类型安全;但是,如果重复实现类型安全容器,则存在复制和粘贴错误的风险。这也可能导致错误。

#2


0  

To make a type which handles generic data in C you would use a void* to pass the data around. It is impractical to define new algorithms for each possible type.

要创建一个处理C中的通用数据的类型,您将使用void *来传递数据。为每种可能的类型定义新算法是不切实际的。

#3


0  

you've no real benefit to using void* as a member (unless, say, compilation times are most important), you can always cast to void* where appropriate, then operate on untyped data blobs where necessary.

使用void *作为成员没有什么好处(除非编译时间最重要),你总是可以在适当的时候转换为void *,然后在必要时对无类型的数据blob进行操作。

i've implemented such interfaces in C (e.g. multiple variants with named fields of different types). i favored having the type safety, and rarely found casting to void* a good thing in these implementations.

我在C中实现了这样的接口(例如,具有不同类型的命名字段的多个变体)。我喜欢具有类型安全性,并且很少发现铸造无效*在这些实现中是一件好事。

…then again, i spend more time writing c++ than c :)

...再说一次,我花了更多的时间来编写c ++而不是c :)

#4


0  

So I had a quick search to see if any new clever ideas had emerged in the field of C containers.

所以我快速搜索了一下C容器领域是否出现了任何新的聪明想法。

I found this. It's a pretty thorough attempt at a complete C container library.

我找到了这个。这是一个完整的C容器库的彻底尝试。

It passes around the elements to be contained in void * pointers. There is no attempt to specify structures of a particular type.

它传递要包含在void *指针中的元素。没有尝试指定特定类型的结构。

For type safety you COULD write a "wrapper" macro for each container, that defines a host if inline functions that wrap around an untyped version and provide the type safety. Hopefully they would be optimized away by the compiler, but this isn't always possible. And the macros would be ugly.

对于类型安全,您可以为每个容器编写一个“包装器”宏,如果内联函数包含非类型化版本并提供类型安全性,则定义主机。希望它们会被编译器优化掉,但这并不总是可行的。而宏将是丑陋的。

I guess this is one of the reasons why more (application) programs are written in C++ instead of C. The ability to create complex abstractions in C is limited. You can do it but you generally sacrifice other aspects like performance or maintainability (check out a C GTK program for example).

我想这是为什么更多(应用程序)程序是用C ++而不是C编写的原因之一。在C中创建复杂抽象的能力是有限的。你可以做到,但你通常会牺牲其他方面,如性能或可维护性(例如,查看一个C GTK程序)。

#1


3  

I'd aim for generic containers:

我的目标是通用容器:

  1. Once you get used to it, you just think of void * is meaning the type of something when I don't care about it's type. It's like Object in Java -- where, for a long time, generic containers didn't have type safety either.

    一旦你习惯了它,你只要想到void *就意味着什么类型的东西,当我不关心它的类型。它就像Java中的Object - 很长一段时间,通用容器也没有类型安全性。

  2. You only have one place to make improvements.

    你只有一个地方可以改进。

  3. You don't get the type safety; but with repeated implementations of type safe containers, you run the risk of copy and paste errors. That can lead to errors, too.

    你没有得到类型安全;但是,如果重复实现类型安全容器,则存在复制和粘贴错误的风险。这也可能导致错误。

#2


0  

To make a type which handles generic data in C you would use a void* to pass the data around. It is impractical to define new algorithms for each possible type.

要创建一个处理C中的通用数据的类型,您将使用void *来传递数据。为每种可能的类型定义新算法是不切实际的。

#3


0  

you've no real benefit to using void* as a member (unless, say, compilation times are most important), you can always cast to void* where appropriate, then operate on untyped data blobs where necessary.

使用void *作为成员没有什么好处(除非编译时间最重要),你总是可以在适当的时候转换为void *,然后在必要时对无类型的数据blob进行操作。

i've implemented such interfaces in C (e.g. multiple variants with named fields of different types). i favored having the type safety, and rarely found casting to void* a good thing in these implementations.

我在C中实现了这样的接口(例如,具有不同类型的命名字段的多个变体)。我喜欢具有类型安全性,并且很少发现铸造无效*在这些实现中是一件好事。

…then again, i spend more time writing c++ than c :)

...再说一次,我花了更多的时间来编写c ++而不是c :)

#4


0  

So I had a quick search to see if any new clever ideas had emerged in the field of C containers.

所以我快速搜索了一下C容器领域是否出现了任何新的聪明想法。

I found this. It's a pretty thorough attempt at a complete C container library.

我找到了这个。这是一个完整的C容器库的彻底尝试。

It passes around the elements to be contained in void * pointers. There is no attempt to specify structures of a particular type.

它传递要包含在void *指针中的元素。没有尝试指定特定类型的结构。

For type safety you COULD write a "wrapper" macro for each container, that defines a host if inline functions that wrap around an untyped version and provide the type safety. Hopefully they would be optimized away by the compiler, but this isn't always possible. And the macros would be ugly.

对于类型安全,您可以为每个容器编写一个“包装器”宏,如果内联函数包含非类型化版本并提供类型安全性,则定义主机。希望它们会被编译器优化掉,但这并不总是可行的。而宏将是丑陋的。

I guess this is one of the reasons why more (application) programs are written in C++ instead of C. The ability to create complex abstractions in C is limited. You can do it but you generally sacrifice other aspects like performance or maintainability (check out a C GTK program for example).

我想这是为什么更多(应用程序)程序是用C ++而不是C编写的原因之一。在C中创建复杂抽象的能力是有限的。你可以做到,但你通常会牺牲其他方面,如性能或可维护性(例如,查看一个C GTK程序)。