如果两种类型不相同,则导致 C89 中的编译错误
Posted
技术标签:
【中文标题】如果两种类型不相同,则导致 C89 中的编译错误【英文标题】:Cause compilation error in C89 if two types are not the same 【发布时间】:2013-02-05 21:35:22 【问题描述】:仅使用 C89 的特性,给定
typedef [unspecified token sequence] T1;
typedef [another unspecified token sequence] T2;
展示一种语言结构,当且仅当 T1 和 T2 是相同类型(不仅仅是兼容)时,该语言结构将无错误地编译。对 C89 的限制是因为这将进入 autoconf 探测。
编辑:我需要一个即使 T1 或 T2 或两者都是不完整类型的解决方案。很抱歉之前没有提到这一点。
编辑之子:所有三个当前答案仅检测兼容类型。事实证明,这比我记得的更接近“相同类型”,对于我目前的目的来说足够接近,但出于好奇,我仍在寻找检测 相同 类型的答案。以下是一些兼容但不相同的类型:
typedef void (*T1)(void);
typedef void (*T2)();
typedef float T1[];
typedef float T2[12];
typedef enum ONE, TWO, THREE T1;
typedef /* implementation-defined integer type */ T2;
【问题讨论】:
我想编译器警告不够好? @NikosC。如果用-Werror
编译,警告会变成错误,所以应该没问题。
出于操作原因,我更希望出现硬错误(不必在 autoconf 探测中使用 CFLAGS),但会发出警告。
见:***.com/questions/9229601/what-is-in-c-code
@technosaurus 如果 expression (从技术上讲,一个整数常量表达式)计算结果为某个固定值,则有几种这样的技巧可以使构建失败,但据我所知,它们都不能用于测试 C89 中的 type 相等性。
【参考方案1】:
我认为您应该能够利用 extern
声明的严格类型检查:
typedef int T1;
typedef char T2;
extern T1 t1;
T2 t1;
以上将无法编译。将 T2 更改为 int
将允许源代码正确构建。
这也不会编译:
typedef int T1;
typedef unsigned int T2;
extern T1 t1;
T2 t1;
尽管这两种类型都是int
。我认为这是您想要的。
但是,这不会触发错误:
typedef emum Foo T1;
typedef unsigned T2;
所以它不是 100% 防水的。但是,必须牢记,enum
不能做任何事情,unsigned
也不能做任何事情。它们具有相同的布局,可以互换使用。实际上,它们是同一类型。
【讨论】:
不错!是的,这就是我想要的行为。在我接受您的回答之前,我将准确检查标准对这个结构的描述,但我很确定您是对的。 在检查 C99 时,如果T1
或 T2
或两者都是不完整的类型,这将不起作用。这可以通过使t1
的两个声明分别指向T1
和T2
来解决。此外,从技术上讲,它只要求 T1 和 T2 是 兼容 类型。事实证明,这比我记忆中的“相同类型”更接近,并且可能符合我的目的,但我仍然很好奇是否可以检测到严格的类型相等。
@Zack 我不确定你的意思。如果类型不同,我无法编译它。你能举一个例子,它在类型不同的情况下编译吗?
@Zack 没关系,我找到了一个使用 emum 的反例。【参考方案2】:
T1 t1;
T2 *t2 = &t1;
如果 T1 和 T2 不相同,则违反约束。
或者,
T1 f();
T2 f()
【讨论】:
这些也只检测兼容类型,而不是相同类型。 嗯。后者不应该要求 same 类型,而不仅仅是兼容吗? 函数原型返回类型方法似乎与extern
答案具有相同的结果,包括没有将enum
与unsigned
视为不同。
对于比 6.7p4 更严格的函数定义,我找不到任何约束(在 C99 中;我没有 C89 的电子副本)“在同一范围内引用的所有声明相同的对象或函数应指定兼容的类型。”并且 6.7.5.3p15 说“对于两个兼容的函数类型,两者都应指定 compatible 返回类型。此外,[...]”(强调我的)。以上是关于如果两种类型不相同,则导致 C89 中的编译错误的主要内容,如果未能解决你的问题,请参考以下文章
C99中的restrict和C89的volatilekeyword
踩坑-编译错误:FastJson与lombok导致找不到符号:方法getId()