C语言中实现定义行为的澄清

C语言中实现定义行为的澄清,c,types,implementation,C,Types,Implementation,作为C中实现定义行为的一个例子,C标准说数据类型的大小是由实现定义的。所以,假设sizeofint是实现定义的 此实现定义的行为是否意味着sizeint依赖于平台,或者由编译器供应商定义,或者两者都定义 一旦我编译了代码,当我在不同版本的平台上运行它时,实现依赖关系是否仍然适用?在一个平台上编译实现定义的代码并在另一个平台上运行会导致性能损失吗 是的,实现定义意味着它取决于平台体系结构+操作系统ABI+编译器 是的,在平台的不同版本中,实现定义的功能可能有所不同。sizeint确实依赖于实现。它

作为C中实现定义行为的一个例子,C标准说数据类型的大小是由实现定义的。所以,假设sizeofint是实现定义的

此实现定义的行为是否意味着sizeint依赖于平台,或者由编译器供应商定义,或者两者都定义

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


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


是的,在平台的不同版本中,实现定义的功能可能有所不同。

sizeint确实依赖于实现。它与性能无关,而是与您正在使用的平台的体系结构有关。32位宽的CPU与64位宽的CPU甚至16位宽的CPU表现不同


这是他们通常所说的平台依赖,但也有交叉编译的问题,这带来了更多的问题。您可以使用-m这样的标志来指定体系结构和宽度,这会导致代码在不同的平台下运行,而不是在最初编译的平台上运行。

根据C标准

ISO/IEC 9899:1999§3.4.1

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

这意味着编译器中记录的行为是实现定义的

sizeof被记录在案

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

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

此实现定义的行为是否意味着sizeint依赖于平台,或者由编译器供应商定义,或者两者都定义

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

以下是C标准中“实施”一词的实际定义:

C99,3.12p1实现:一组特定的软件,在特定的控制选项下运行于特定的翻译环境中,为特定的执行环境执行程序翻译,并支持在特定的执行环境中执行功能

此实现定义的行为是否意味着sizeint依赖于平台,或者由编译器供应商定义,或者两者都定义

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

针对多个平台和体系结构的编译器将作为每个平台配置的一部分分别做出决策。然后,每个目标表示不同的C实现,即使您认为它是同一个编译器

您可以编写一个一致的C实现,其中int的大小与运行该程序的操作系统上的int的大小不同。人们很少这样做,而且标准库在进行系统调用时必须跳过额外的环。作为仿真器的一部分,它可能很有用,但是您可能会合理地认为该平台是仿真平台,而不是具有不同大小int的主机平台

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

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

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

如果它真的起作用,那么就没有特别的理由认为会出现性能损失。它通常根本不起作用,如上文所述,因为通常用于一个平台的二进制代码在另一个平台上不起作用。如果平台足够相似,它确实可以工作,那么编译器为其中一个平台所做的优化可能不是对另一个平台的很好优化。在这种情况下,将出现性能损失,修复方法是重新编译针对平台正确版本的代码

这种情况在ARM上确实发生过,在x86上发生的情况更少。过去不同的芯片提供了基本相同的指令集,但某些芯片上的某些指令具有明显不同的特性
相对于其他指令的成本。假设指令X快的优化在指令X慢的不同芯片上可能是不好的优化。正如你所能想象的,这种差异并没有使芯片制造商在编译器供应商中大受欢迎,在汇编程序员中更是如此。

有很多帖子都是关于第一个问题的,比如说。如果我创建代码的可执行版本并在不同的体系结构系统上运行,大小会改变吗?@AshRj不,程序根本不会运行,正是因为大小不同。@Let_Me_Be:你的意思是,如果我在Windows XP上编译某个东西,那么它就不会在Windows 7上运行,因为正如你所说,实现定义的功能可能在不同版本的平台上有所不同?我会很惊讶。@user963241,这就是我写can和notwill的原因。@Let_Me_be我担心,即使在大小出现问题之前,架构也会阻止可执行文件运行。.-事实上,如果程序在不同大小的系统上运行,这取决于具体情况。以AMD64和x86为例。问:但是编译器受到平台OS/体系结构的约束吗?@GrijeshChauhan一些实现定义的行为受到ABI的约束。这就是为什么编译器文档有时会针对一些实现定义的行为重定向到ABI。否则,一些实现定义的行为选择是为了适应硬件,而另一些是出于历史原因。@ouah:实现是编译器-我不认为这完全正确。编译器是您对实现的直接访问点,但实现也包含不属于编译器的内容,包括执行程序的环境。@SteveJessop在某种程度上是的。C定义了C99,3.12p1中的实现术语的含义。我在回答中加了一个引号,或者更确切地说:编译器必须记录所有实现定义的行为,否则它就不符合标准。因此,如果您的编译器没有记录例如sizeofint有多大,那么严格地说,您的编译器不是C编译器。@Lundin:编译器的文档中指定,例如,对将超出范围的值强制转换为int的结果执行的任何计算都可能产生任意值,这是否合法,或者需要文档来指定某些特定的一致性行为?