【问题标题】:Can int and long be the same type?int 和 long 可以是同一类型吗?
【发布时间】:2013-02-14 12:10:08
【问题描述】:

当然,intlong保证是同一类型,而是在 Windows 等平台上以 32 位模式编译时它们恰好大小相同,编译器是否允许将它们视为同一类型?

我不确定如何明确测试编译器是否将两种类型视为相同,但我尝试使用int *a; long *b = a; 进行启发式测试,Microsoft 编译器毫无怨言地接受了这一点,而 GCC 则发出警告。是编译器行为不正确,还是依赖于实现,它们是命名两种不同的类型还是只命名一种?

【问题讨论】:

  • 指向数据的指针往往具有same size regardless of their type,这可能就是您可以将一个分配给另一个的原因。我猜 MS 编译器只是没有给你警告。
  • 为了澄清,微软编译器确实警告 int *a;字符 *b = a;
  • 从技术上讲,它们不是“同一类型”,但根据 ABI 定义,它们的大小确实相同。我还猜测有足够多的地方编写了一些代码,因为知道 intlong 的大小相同,以至于来自 MS 编译器的警告对于 MS 内部开发人员来说是非常烦人的。
  • 绝对不是(尽管我把它留给了一个答案,以便在标准中挖掘它)。好的,在 C 中,它既没有函数重载也没有typeid,不过,我不知道如何轻松地检查这一点。但我也猜你的支票不是那么可靠。
  • 将这种行为与 c++ 进行比较很有趣——在 c++ 中,它们当然不应该是相同的类型,并且赋值会出错。对于 C,您可以将 void* 分配给任何指针类型。所以不确定这里的规则。从 c++ 中函数重载的角度来看,long 不应与 int 类型相同(在 C 中不是问题)。

标签: c


【解决方案1】:

标准(C2011标准的N1570草案)在6.2.5(4)中说:

有五种标准有符号整数类型,指定为signed charshort intintlong intlong long int。 (这些和其他类型可以用几种额外的方式指定,如 6.7.2 中所述。)也可能存在实现定义的扩展有符号整数类型。标准和扩展的有符号整数类型统称为有符号整数类型。

在同一部分的第 14 段中:

类型char,有符号和无符号整数类型,浮点类型是 统称为基本类型。基本类型是完整的对象类型。即使 实现定义了两个或多个基本类型以具有相同的表示,它们是 然而不同的类型。

也就是说intlong(另一种指定long int)是不同的类型。它们可能具有相同的表示、行为和对齐要求,但就语言而言,它们的类型不同。

【讨论】:

  • 在 C++ 中,类型不同意味着您可以基于类型不同这一事实进行重载、模板特化等。如果不同类型具有相同的表示、对齐要求和行为,它们在 C 中会产生什么实际影响?
  • 本节的第 14 段更好地说明它们是不同的类型,请参阅我的回答。
  • @ChristianRau 对。不过,我不能那么快地阅读(更不用说打字了),所以我仍在寻找和整合它的过程中。
  • @ArmenTsirunyan:如果它们是相同的类型,你可以做一些事情,因为它们不同,是 UB。例如,通过long* 访问int。由于它们是不同的类型,我无法想到你可以在 C 中做的任何事情,如果它们是相同的,你就无法做到。但如果没有别的,它们是不同的类型意味着编译器可以警告可能缩小隐式转换,而这些隐式转换恰好不会缩小执行警告的实现。所以它在实践中很有用,即使它不能保证任何事情。
  • @ArmenTsirunyan 实际上可能没有太多实际意义,这就是为什么你不能那么容易地测试它们的独特性的原因(而在 C++ 中,使用函数重载或只是 typeid 很容易)。
【解决方案2】:

好的,C99 标准在 6.5.6 类型部分中说:

有五种标准的有符号整数类型,指定为有符号 charshort intintlong intlong long int。 (这些和其他类型可以通过几种其他方式指定, 如 6.7.2 所述。)也可能有实现定义的 扩展的有符号整数类型。标准和扩展的有符号整数类型统称为有符号整数类型

此外:

char 类型,有符号和无符号整数类型,以及 浮动类型统称为基本类型。即使 实现定义了两个或多个基本类型具有相同的 表示,但它们是不同的类型。

这清楚地表明它们必须是不同的类型,即使在没有模板、函数重载和typeid 的 C 中,它可能不像在实际中那么重要C++,那些类型是 相同的 类型肯定会破坏很多代码。

编辑:事实上,由于 C 中类型独特性的实际相关性较小并且缺少上述语言特征,我无法想出一个可靠的方法立即测试两种类型的绝对区别。

【讨论】:

  • 好的,就摘要中的语言定义而言,这已经足够清楚了,谢谢。现在我仍然想知道的是:为一种设计为 C 超集的语言编写一个编译器,没有你提到的 C++ 特性,我可以继续前进,只表示类型内部为 i8、i16、i32、i64,还是有任何情况会导致编译器无法生成正确的代码?
  • @rwallace 您的意思是您希望能够正确地完成 C 可以做的所有事情,同时又不严格遵守 C 标准?很难说,因为我不知道类型区分是否真的有任何实际含义,无论它可能有多小。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-21
  • 2017-06-06
  • 1970-01-01
  • 2017-01-04
  • 2017-09-25
  • 2010-10-25
相关资源
最近更新 更多