【问题标题】:can gcc warn on assignment of void pointer to more specific pointer?gcc 可以警告将 void 指针分配给更具体的指针吗?
【发布时间】:2017-03-08 05:11:00
【问题描述】:

当void* 被分配或作为参数传递给更具体的指针类型时,我如何使gcc 发出警告,例如没有强制转换的my_struct*?我想确保所有的转换都是明确的。

更新:此问题的范围也已扩展到非gcc linters。

Update2:到处都是缺点?一个简单的纯技术问题会引发如此多的争议,这让我感到困惑。

【问题讨论】:

  • @GabrieleB-David Yup.
  • @GabrieleB-David 我想显而易见的解决方法是 typedef { } opaque_t 并在任何地方使用 opaque_t* 而不是 void* 但如果有人有更好的想法或知道非gcc linter 可以做这个检查。
  • @GabrieleB-David: void * 可以分配给 C 中的任何其他指针类型。OP 询问有关没有意义的合法表达式的警告。
  • @DepressedDaniel:这将违反有效类型规则,因此调用 UB。只需介绍编码风格指南并信任您的同行。 C中有足够多的其他东西,你可以射击你的脚、手臂和头部。如果您已经对此有疑问,您应该考虑使用强类型语言。想到了 Ada,或者 Python(从你的问题来看,我怀疑动态类型的语言也会是编码纪律的问题)。

标签: c gcc c99


【解决方案1】:

当void* 被分配或作为 参数类型是更具体的指针类型

能够在不进行强制转换的情况下将void * 分配给更具体的类型是C 编程语言的必需部分。根据 the C Standard 的 6.3.2.3 指针 的第 1 段:

指向void 的指针可以转换为指向任何 对象类型。 指向任何对象类型的指针都可以转换为 指向void 的指针并再次返回;结果应比较相等 到原来的指针。

您要求收到有关 C 的必需部分的警告。将 5 分配给 int 时,要求收到警告并不遥远。

正如@MarcGlisse 指出的那样,GCC does provide the -Wc++-compat warning option:

-Wc++-compat(仅限 C 和 Objective-C)

警告 ISO C 结构超出 ISO C 和 ISO C++ 的公共子集,例如请求从 void * 隐式转换为指向非void 类型的指针。

【讨论】:

  • 呃,你确实意识到当事情不合法时,编译器会尝试报告错误,而警告通常是关于合法(但可疑)的事情?作为“C 的必需部分”并不是不警告的论据。成为最佳实践/常见习语是更好的理由。
  • @MarcGlisse 在C 中,分配void * 指针不进行强制转换 不仅完全可以接受,而且在许多方面实际上更可取。 the fourth-highest ranked question on all of Stackoverflow 上的 highest ranked answer 特别声明将void * 分配给特定的指针类型没有强制转换。强制转换 void * 不是 C 中的“最佳实践”不是,并且存在不强制转换的重要论据。同样,这就像在 int x = 5; 上要求警告一样。
  • 我同意对此的警告是错误的。我说的是“C 的必需部分”是错误的论点,你刚才在评论中写的是一个更有力的论点。
  • a&&b||c 的语义是 C 的必需部分,gcc 仍然会警告缺少括号。未使用的变量是 C 的必需部分,gcc 仍然会发出警告。等等。初步近似:非法 -> 错误,合法(但有问题) -> 警告。
  • @DepressedDaniel 你为什么要使用 void*? void* 的要点是隐式转换。否则,您可以只使用 char*。
【解决方案2】:

正如@MarcGlisse 所述,gcc 提供了-Wc++-compat 警告选项。在其他不兼容C++ 的结构中,它会警告void* 的静默转换。

@AndrewHenle 链接到另一个问题的答案,该问题表明要求显式转换具有增加可能导致不兼容转换的可能性的缺点,例如,如果程序员不小心转换了数值。

我认为这不是问题,因为通过显式转换,程序员可以证明他们知道自己在做什么。尽管如此,即使是这个小缺点也可以通过将以下宏与-Wc++-compat 结合使用来解决:

#define VOID_CAST(T, x) ({ __typeof__(x) void_cast_x __attribute__((__unused__)) = ((__typeof__(x))((void*)(x))); ((T*)(x)); })

如果运气好的话,“无用”的分配将被优化掉,使用VOID_CAST 的好处是,如果x 不是void* 开始,它将产生错误或警告。

【讨论】:

    猜你喜欢
    • 2015-01-15
    • 2014-05-13
    • 1970-01-01
    • 2013-12-10
    • 1970-01-01
    • 2016-09-25
    • 1970-01-01
    • 2013-04-08
    • 2014-08-23
    相关资源
    最近更新 更多