实现是否可以将提示视为实际语句?
Can an implementation consider hints as actual statements?
在 C 中,register
存储限定符 提示 应尽快访问此类标识符的实现(例如存储在 CPU 注册).
§6.7.1
A declaration of an identifier for an object with storage-class specifier register suggests that access to the object be as fast as possible. The extent to which such suggestions are effective is implementation-defined.
和
§6.7.3 The intended use of the restrict qualifier (like the register storage
class) is to promote optimization [...]
但是,我听说过一些实现(特别是在嵌入式系统中),其中 register
具有更强的含义:它是一个 命令 并且编译器应将寄存器中的合格标识符。
那么,实现是否允许遵循该行为并因此被视为符合标准?什么会允许这样做?
我提出这个问题是因为我发现有义务将该对象放入寄存器中不再是标准规定的建议;换句话说,它们相互冲突。
只要不阻止格式良好的程序编译或以任何方式影响标准中指定的观察到的行为,就允许这样做。
标准已经禁止使用 register
说明符声明的对象的地址或对齐方式,因此这部分不会有问题。更棘手的情况是,如果您使用 register
声明的对象多于可用寄存器的数量。除非实现仍然允许 register
对象溢出(暂时将值从寄存器移动到堆栈,然后返回),否则这将是实现无法编译符合标准的程序的情况。
如你所言,标准说"The extent to which such suggestions are effective is implementation-defined."
这为实施提供了自由空间,可以做任何事情,从忽略建议到竭尽全力实施它。选择接受 register
说明符作为要求使用寄存器的实现当然不与标准相矛盾,而且不考虑说明符而仅自行决定寄存器放置的实现也不与标准相矛盾。
实现不应该做的一件事是拒绝编译程序,因为它需要溢出 register
—— 至少要达到 §5.2.4.1 中指定的限制 Translation limits——但没有什么能阻止编译器发出警告。 (没有什么能阻止编译器发出关于任何事情的警告;编译器通常会警告被认为是危险的完全合法的构造。)
编辑: 重读 5.2.4.1,在我看来,一个实现实际上可能会拒绝编译它认为有太多 register
说明符的程序,因为 limits 子句只绑定能够翻译和执行 "one program" 的实现,其中包括(例如)“在一个块中声明的具有块范围的 511 标识符”,而不是任何这样做的程序。据我所知,编译器可以坚持认为达到该限制的 "at least one program" 没有任何 register
规范。
注意:并不是所有的 CPU 都有常识性的寄存器,但标准实际上并没有说明任何关于硬件的内容。它只是说 register
说明符传达了程序员制作 "access to the object be as fast as possible" 的愿望。此外,编译器为满足这种需求而进行的尝试实际上并不需要优化对对象的访问;优化尝试失败并不违反标准。
在 C 中,register
存储限定符 提示 应尽快访问此类标识符的实现(例如存储在 CPU 注册).
§6.7.1 A declaration of an identifier for an object with storage-class specifier register suggests that access to the object be as fast as possible. The extent to which such suggestions are effective is implementation-defined.
和
§6.7.3 The intended use of the restrict qualifier (like the register storage class) is to promote optimization [...]
但是,我听说过一些实现(特别是在嵌入式系统中),其中 register
具有更强的含义:它是一个 命令 并且编译器应将寄存器中的合格标识符。
那么,实现是否允许遵循该行为并因此被视为符合标准?什么会允许这样做?
我提出这个问题是因为我发现有义务将该对象放入寄存器中不再是标准规定的建议;换句话说,它们相互冲突。
只要不阻止格式良好的程序编译或以任何方式影响标准中指定的观察到的行为,就允许这样做。
标准已经禁止使用 register
说明符声明的对象的地址或对齐方式,因此这部分不会有问题。更棘手的情况是,如果您使用 register
声明的对象多于可用寄存器的数量。除非实现仍然允许 register
对象溢出(暂时将值从寄存器移动到堆栈,然后返回),否则这将是实现无法编译符合标准的程序的情况。
如你所言,标准说"The extent to which such suggestions are effective is implementation-defined."
这为实施提供了自由空间,可以做任何事情,从忽略建议到竭尽全力实施它。选择接受 register
说明符作为要求使用寄存器的实现当然不与标准相矛盾,而且不考虑说明符而仅自行决定寄存器放置的实现也不与标准相矛盾。
实现不应该做的一件事是拒绝编译程序,因为它需要溢出 register
—— 至少要达到 §5.2.4.1 中指定的限制 Translation limits——但没有什么能阻止编译器发出警告。 (没有什么能阻止编译器发出关于任何事情的警告;编译器通常会警告被认为是危险的完全合法的构造。)
编辑: 重读 5.2.4.1,在我看来,一个实现实际上可能会拒绝编译它认为有太多 register
说明符的程序,因为 limits 子句只绑定能够翻译和执行 "one program" 的实现,其中包括(例如)“在一个块中声明的具有块范围的 511 标识符”,而不是任何这样做的程序。据我所知,编译器可以坚持认为达到该限制的 "at least one program" 没有任何 register
规范。
注意:并不是所有的 CPU 都有常识性的寄存器,但标准实际上并没有说明任何关于硬件的内容。它只是说 register
说明符传达了程序员制作 "access to the object be as fast as possible" 的愿望。此外,编译器为满足这种需求而进行的尝试实际上并不需要优化对对象的访问;优化尝试失败并不违反标准。