繁体   English   中英

如果 C 中的两种类型相互“兼容”,这究竟意味着什么?

[英]What does it mean exactly if two types are “compatible” to each other in C?

在 C 标准中规定(强调我的):

如果它们的类型相同,则两种类型具有兼容的类型。 用于确定两种类型是否兼容的附加规则在 6.7.2 中描述了类型说明符,在 6.7.3 中描述了类型限定符,在 6.7.6 中描述了声明符。 56)

56) 两种类型不必相同才能兼容

来源:C18,§6.2.7/1 - “兼容类型和复合类型”

我从这些句子中得到的信息不多,也不是很有帮助。 所引用的部分通常也没有提供有关“兼容”究竟是/意味着什么的进一步信息。

我现在知道,如果两种类型具有相同的类型,则它们是兼容的,但如果它们不具有相同的类型/相同,它们也可以兼容。

我发现两种不同类型彼此兼容的地方是,如果我将一种类型与该原始类型的typedef d 类型或原始类型的任何typedef d 类型进行比较,两种类型都是兼容的,如在§6.7.8/4 和 /5 的示例:

§6.7.8/4:

示例 1之后

typedef int MILES, KLICKSP(); typedef struct {doublehi, lo; } range;

建筑

MILES distance; extern KLICKSP *metricp; range x; range z,*zp;

都是有效的声明。 distance的类型是intmetricp的类型是“指向function的指针,没有参数说明返回int ”, xz的类型是指定的结构体; zp是指向这种结构的指针。 object distance具有与任何其他int object 兼容的类型

§6.7.8/5:

示例 2在声明之后

typedef structs1 { int x; } t1, *tp1; typedef structs2 { int x; } t2, *tp2;

类型t1tp1指向的类型是兼容的。 类型t1也与类型structs1兼容,但与类型structs2t2tp2指向的类型或int不兼容

但它只显示了一个关于typedef的示例,其中类型如果不相同则可以兼容

我的问题:

  • 如果两种类型不完全相同,在哪种(所有)情况下可以兼容 , 和

  • 究竟什么是“兼容类型”? / 如果两种类型相互兼容,这意味着什么?

  • 什么指定了“兼容性”?

这就是我正在寻找的东西,直到现在还没有在标准中找到。

如果可能,请参阅答案中标准的部分。


补充研究:

我发现兼容性不是与范围、表示或行为相关的强制性要求:

§6.2.5/15:

charsigned charunsigned char这三种类型统称为字符类型 实现应将char定义为与有signed charunsigned char具有相同的范围、表示和行为.45)

45) <limits.h>中定义的CHAR_MIN将具有值0SCHAR_MIN之一,这可用于区分这两个选项。 无论做出何种选择, char都是与其他两种不同的类型,并且与任何一种都不兼容


从第一个引用中引用的部分:

引用的第 6.7.2、6.7.3 和 6.7.6 节没有更多地解释什么是兼容类型,它们仅在类型应为兼容类型时规定了特定情况的规则。

§6.7.2/4:

每个枚举类型应与 char、有符号 integer 类型或无符号 integer 类型兼容。 类型的选择是实现定义的,131) 但应该能够表示枚举的所有成员的值。 枚举类型在终止枚举器声明列表的 } 之后是不完整的,然后是完整的。

§6.7.3/11:

对于要兼容的两个限定类型,两者都应具有兼容类型的相同限定版本; 说明符或限定符列表中类型限定符的顺序不影响指定的类型。

§6.7.6.1/2:

对于要兼容的两种指针类型,两者都应具有相同的限定,并且都应是指向兼容类型的指针。

§6.7.6.2/6:

对于要兼容的两个数组类型,两者都应具有兼容的元素类型,并且如果两个大小说明符都存在,并且是 integer 常量表达式,则两个大小说明符应具有相同的常量值。 如果在需要它们兼容的上下文中使用这两种数组类型,则如果这两个大小说明符计算为不相等的值,则这是未定义的行为。

§6.7.6.3/15:

对于要兼容的两个 function 类型,两者都应指定兼容的返回类型。149) 此外,参数类型列表(如果两者都存在)应在参数数量和省略号终止符的使用方面达成一致; 相应的参数应具有兼容的类型。 如果一种类型具有参数类型列表,而另一种类型由 function 定义的一部分且包含空标识符列表的 function 声明符指定,则参数列表不应有省略号终止符,并且每个参数的类型应与应用默认参数提升所产生的类型兼容。 如果一种类型具有参数类型列表,而另一种类型由包含(可能为空)标识符列表的 function 定义指定,则两者在参数数量上应一致,并且每个原型参数的类型应与类型兼容这是由于将默认参数提升应用于相应标识符的类型而产生的。 (在确定类型兼容性和复合类型时,每个用 function 或数组类型声明的参数都被认为具有调整后的类型,每个用限定类型声明的参数都被认为具有其声明类型的非限定版本。)

149) 如果 function 类型都是“旧式”,则不比较参数类型。


有关的:

它实际上来自于:

  1. 所有引用相同 object 或 function 的声明应具有兼容类型; 否则,行为未定义。

因此,您可以从中看到标准允许在这里工作的任何东西,必然是兼容的。 例如int []类型与int [10]不同,但它们是兼容的,因为标准允许您声明

extern int foo[];

在一个文件中并定义

int foo[10];

在另一个文件中,并使用外部标识符作为未知大小的数组访问foo - 因此这些类型是兼容的,但不相同。

C11/18 6.7.6.2p6中明确说明:

  1. 对于要兼容的两个数组类型,两者都应具有兼容的元素类型,并且如果两个大小说明符都存在,并且是 integer 常量表达式,则两个大小说明符应具有相同的常量值。 如果在需要它们兼容的上下文中使用这两种数组类型,则如果这两个大小说明符计算为不相等的值,则这是未定义的行为。

非常感谢您的提问。 我在试图揭示“如果类型相同,则两种类型具有兼容类型”这句话背后可能存在什么问题时碰到了它。 您帮助我意识到它仅说明了两种类型兼容的充分条件。

在我的理解中,兼容性关系最重要的属性是它克服了结构/联合标记或类型定义名称的scope 特别是,C17 直接声明(§6.7.2.3/5):

位于不同范围或使用不同标记的结构、联合或枚举类型的两个声明声明了不同的类型。

也就是说,在两个或多个文件中使用相同的结构/联合声明会产生不同但兼容的类型。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM