0

作为 C 中实现定义行为的一个示例。C 标准说数据类型的大小是实现定义的。所以,说sizeof(int)是实现定义的。

  1. 这种实现定义的行为是否意味着size(int)依赖于平台或由编译器供应商定义或两者兼而有之?

  2. 一旦我编译了我的代码,当我在不同版本的平台上运行它时,实现依赖关系是否仍然适用?在一个平台上编译实现定义的代码并在另一个平台上运行它会导致性能损失吗?

4

5 回答 5

3

是的,实现定义意味着它取决于平台(架构 + 操作系统 ABI + 编译器)。

是的,实现定义的功能可能因平台的不同版本而异。

于 2012-12-04T07:05:04.180 回答
3

此实现定义的行为是否意味着 size(int) 取决于平台或由编译器供应商定义或两者兼而有之?

原则上,编译器供应商可以做出该决定。在实践中,如果编译器想要发出直接调用系统库的代码,那么它必须遵循与系统相同的“ABI”(应用程序二进制接口),除此之外,ABI 将指定int. 因此编译器供应商将“决定”使其达到 ABI 所说的大小。

针对多个平台和架构的编译器将作为每个平台配置的一部分单独做出决定。然后,每个目标都代表一个不同的C 实现,即使您将其视为“相同的编译器”。

您可以编写一个符合标准的 C 实现,其中int的大小与运行程序的操作系统上的大小不同。人们很少这样做,并且标准库在进行系统调用时不得不跳过额外的环节。它作为模拟器的一部分可能很有用,但是您可能会合理地争辩说“平台”是模拟平台,而不是具有不同大小 int 的主机平台。

一旦我编译了我的代码,当我在不同版本的平台上运行它时,实现依赖关系是否仍然适用?

sizeof(int)是一个编译时常量,这意味着您的编译器发出的代码可能会采用某个值。然后,该二进制代码无法在具有不同大小的平台的不同版本上正确运行int

在一个平台上编译实现定义的代码并在另一个平台上运行它会导致性能损失吗?

如果它完全有效,那么没有特别的理由假设会有性能损失。它通常根本不起作用(见上文),因为通常用于一个平台的二进制代码在另一个平台上不起作用。如果平台足够相似以至于它确实可以工作,那么编译器为一个平台所做的优化可能在另一个平台上并不是那么好的优化。在这种情况下,会出现性能损失,解决方法是重新编译针对正确(版本)平台的代码。

这确实发生在 ARM 上,在 x86 上发生的程度较小。过去不同的芯片提供基本相同的指令集,但某些芯片上的一些指令相对于其他指令具有显着不同的成本。假设指令 X 很快的优化可能是在指令 X 很慢的不同芯片上的糟糕优化。正如你可以想象的那样,这种差异并没有使芯片制造商在编译器供应商中大受欢迎,在汇编程序员中更是如此。

于 2012-12-04T09:07:44.673 回答
2

此实现定义的行为是否意味着 size(int) 取决于平台或由编译器供应商定义或两者兼而有之?

在 C 标准术语中,实现是编译器。

这是术语implementation的 C 标准的实际定义:

(C99, 3.12p1) implementation:特定的软件集,在特定的控制选项下在特定的翻译环境中运行,为特定的执行环境执行程序翻译,并支持在特定执行环境中执行功能

于 2012-12-04T07:22:08.877 回答
0

size(int) 确实依赖于实现。它与性能无关,而与您正在使用的平台的架构有关。32 位宽的 CPU 的行为与 64 位宽的 CPU 甚至 16 位宽的 CPU 的行为不同。

这就是他们主要指的平台依赖,但也存在交叉编译的问题,这带来了更多的问题。您可以使用 -m 之类的标志来指定架构和宽度,这会导致代码在与最初编译时不同的平台上运行。

于 2012-12-04T07:09:29.160 回答
0

根据C-标准

ISO/IEC 9899:1999 §3.4.1

1实现定义的行为
未指定的行为,其中每个实现都记录了如何做出选择`

这意味着编译器中记录的行为是implementation defined.

sizeof()记录在案。

2 示例:实现定义行为的一个示例是当有符号整数右移时高位的传播。

附件 J“可移植性问题”包括未指定行为 (J.1)、未定义行为 (J.2)、实现定义行为 (J.3) 和区域特定行为 (J.4) 的列表。

于 2012-12-04T07:09:40.183 回答