【问题标题】:How can one avoid mistakenly casting a void* to the wrong type?如何避免错误地将 void* 转换为错误的类型?
【发布时间】:2012-03-22 00:13:27
【问题描述】:

在 C 中编程,是否有任何技术可以用来避免(或至少最小化)将 void * 错误地转换为错误的指针类型?我正在开发一个程序,它解析几种不同类型的 CSV 数据文件并将字段存储到特定的数据结构中进行处理。例如,其中一个数据文件的记录存储在哈希表中;来自另一个文件的数据存储在有向图中。

我想创建一个主要的解析函数,它从文件中读取字段记录,并将每条记录传递给一个函数,该函数对字段进行标记并将它们存储在适当的数据类型中。我不想为每种文件类型创建单独的解析/标记化函数,而是想创建一个通用函数来执行此操作。在我的设计中,调用函数将传递一个字段记录、一个指向适用于数据文件的标记器的函数指针,以及一个指向适用于数据文件的目标数据结构节点的 void*。

我想知道的是,有没有什么办法可以保证用户不会错误的调用解析器和不匹配的分词器/数据结构的函数。 (通过使用指向 void 的指针,编译器在这里肯定是束手无策。)或者,如果没有这样的技术,是否有任何有效的异常处理方法来捕捉这个错误并防止重大问题(例如,sigfaults)?

我希望代码尽可能可移植。

有什么想法吗?我没有嫁给这个算法,如果有人有更好的想法,我愿意接受。

【问题讨论】:

  • 在你的结构前面加上一个类型字段并在转换后检查它?
  • 我很确定答案是否定的;当您使用 void* 时,您选择自己跟踪数据类型。
  • 你可以创建struct {unsigned short char type; void *data;}
  • @Kevin - 我认为这与我得出的结论相同。 James 和 Vyktor——这些都是我认为可以解决问题的好建议。我会试试看。

标签: c pointers void


【解决方案1】:

一种可能性是创建一组非常薄的包装函数来抽象出类型安全问题:

void foo_generic(FieldRecords *records, Parser *parser, void *dest);

...

void foo_A(FieldRecords *records, A *dest) { foo_generic(records, &parse_A, dest); }
void foo_B(FieldRecords *records, B *dest) { foo_generic(records, &parse_B, dest); }
void foo_C(FieldRecords *records, C *dest) { foo_generic(records, &parse_C, dest); }

现在所有可能的拼写错误都被限制在一个位置,由于对称性,错误应该更容易被发现。

如果你觉得特别顽皮,你可以使用宏来简化这些包装函数的生成:

#define FOO(T) void foo_##T(FieldRecords *records, T *dest) { \
                   foo_generic(records, &parse_##T, dest); \
               }

FOO(A)
FOO(B)
FOO(C)

这最大限度地减少了拼写错误的可能性,但增加了混淆调试器/IDE的机会!

【讨论】:

  • 谢谢,这是一个很好的解决方案。
猜你喜欢
  • 1970-01-01
  • 2013-04-02
  • 1970-01-01
  • 2017-07-27
  • 2016-09-16
  • 2023-04-03
  • 1970-01-01
  • 1970-01-01
  • 2021-11-02
相关资源
最近更新 更多