C语言 在标准中,它在哪里说,当你做按位操作时,它的行为就像big-endian?

2cmtqfgy  于 2023-05-06  发布在  其他
关注(0)|答案(4)|浏览(156)

不管字节序如何,位移位和其他操作总是表现得好像它们是大端序。所以小的数字在右边,大的在左边。左为左为右为右。
我的问题是,它在哪里明确地说这是这样的?我的C11草案副本甚至没有提到endianness,在按位部分有一些我不理解的数学表达式,所以我不确定这部分在哪里。

vbopmzt1

vbopmzt11#

不管字节序如何,位移位和其他操作总是表现得好像它们是大端序。
不,他们没有。“端序”是指对象的字节(有时是位)如何存储在内存中。在C标准中指定的位移位和按位运算符对值进行操作,而不考虑它们在内存中的存储方式,因此不涉及字节序。
移位运算符通过它们的通用名称(“左移位”和“右移位”)和它们在C标准中的规范中的一些术语将较大的位置值与向左位相关联,并且将较小的位置值与向右位相关联,但是这种约定仅指人类如何写入二进制数字。它对如何将值的表示写入内存没有影响。
例如,考虑使用32位unsigned intunsigned int x = 1u << 24;。1将被左移,产生值224,其可以二进制形式写成00000000000000000000000000000。当写入内存时,C实现可能以1,0,0,0(对于大端顺序)或0,0,0,1(对于小端顺序)的顺序存储字节。内存中的这个顺序与值无关,在任何符合32位unsigned int的C实现中,该值仍然是000000001000000000000000000000002。

oo7oh9g9

oo7oh9g92#

从逐位移位运算符的描述可以直接得出结果并不取决于整数的存储方式。
C11标准(6.5.7位移位运算符)
4 E1〈〈E2的结果是E1左移的E2比特位置;用零填充空出的位。如果E1是无符号类型,则结果的值是E1 × 2 E2,比结果类型中可表示的最大值大一模。如果E1具有带符号类型和非负值,并且E1 × 2 E2在结果类型中是可表示的,则这是结果值;否则,行为是未定义的。
5 E1〉〉E2的结果是E1右移E2位位置。如果E1为无符号类型,或者E1为有符号类型且为非负值,则结果的值为E1 /2 E2的商的整数部分。如果E1具有带符号类型和负值,则结果值是实现定义的。
否则,C标准中会有一个关于整数在内存中存储方式的注解。

lh80um4z

lh80um4z3#

在标准中,它在哪里说,当你做按位操作时,它的行为就像big-endian?
正如@Eric所观察到的,这是对C行为的错误描述。按位(以及基本上所有其他)操作是根据操作数的 * 值 * 来定义的,而不是它们在内存中的 * 表示 *。然而,按位移位运算符有点特殊,因为它们实际上突出了差异。
至于在哪里定义,自然是在指定这些操作符的行为的部分中定义的。特别是对于按位移位运算符,这主要是C23第6.5.7/4-5段(以及语言规范早期版本中几乎相同的文本)。相关摘录:
E1 << E2的结果是E1左移E2位位置;用零填充空出的位。如果E1是无符号类型,则结果的值为E1 × 2x 1 m5n1x,环绕。[...]
E1 >> E2的结果是E1右移E2位位置。如果E1为无符号类型,或者E1为有符号类型且为非负值,则结果的值为E1/2x 1 m10n1x的商的整数部分。[...]
请注意,结果是以算术方式定义的,而不是基于存储布局。

jgovgodb

jgovgodb4#

C11具有以下内容:对于6.5.7 Bitwise shift operators下的左移:
E1〈〈E2的结果是[...] E1x2E2,比结果类型[...]中可表示的最大值大一模约简。
无论机器的字节序如何,这个定义都适用,因为它是根据操作产生的语义来描述的,而不是它的内部表示(字节序)。
例如,如果你要对结果值执行一个循环,这个循环要运行多少次迭代?这与目标体系结构决定在内部布局价值的方式无关。
“左”和“右”移位实际上只是所使用的这些操作的常规名称,因为它们在以阿拉伯数字方式(最高有效位向左)书写数字时是直观的。
即使在既不使用little endian也不使用big endian(它们存在)的架构上,该操作仍然被称为左移。C标准中的定义完全与体系结构无关。

相关问题