C99(ISO / IEC 9899:1999)
6.2.6.2/1整数类型任何填充位的值都是未指定的.45)符号位为零的有符号整数类型的有效(非陷阱)对象表示是相应无符号类型的有效对象表示,并代表相同的 Value . 对于任何整数类型,所有位为零的对象表示应该是该类型中零值的表示 .
在C99标准中,保证所有位为零的整数类型表示相应类型中的值 0
. 但是,这是否保证了基础二进制值是我们所期望的?
例如:
unsigned x = 42;
我们通常希望机器将此十进制 42
值存储在内存中作为二进制 101010
值 .
但是,某些偏心机器架构是否可以存储与二进制 011011
值相同的十进制 42
值(不一定是出于实际原因,但仅仅因为它可以)?
如果是这样,请考虑使用右移操作的以下代码:
unsigned y = x>>1; /* 101010>>1 or 011011>>1 */
y
会保持十进制值 21
( 10101
二进制),还是十进制值 13
( 01101
二进制)?
在按位操作之后,C99标准是否对无符号整数类型的十进制表示做出任何保证 - 例如在所有机器架构中,保证等效于 2
的整数除法是正确的吗?
3 回答
标准中未指定整数的表示形式 .
但是,
>>
和<<
的行为是根据位的含义而不是它们的位置来定义的 .因此
>> 1
将表示4的位移动到表示2的位,而不管这些位实际位于何处 .引用C99 standard部分6.5.7:
>>
运算符将移动位 . 在正常系统下,这意味着只是转移它们 . 但实际上,无论它在哪里,我们都会采用代表位置_2585909的位,并将其移动到位置2^2
.所以在所有系统上,
assert(42 >> 1 == 21)
.至于你的第二个问题, yes ,只要你忽略陷阱/填充位 . 那些可能显然是不同的,但通常也是你看不见的 .
该标准不保证事物在物理上如何存储在内存中 . 没有必要这样做 . 机器可以是物理级别的三元组,十进制或模拟,而不是二进制 . 机器甚至不需要物理位 .
所有它保证unsigned int是按位运算符影响"bits"作为数字的二进制位置表示的元素 . 这些实际上是虚拟位 . 它们可以直接对应物理位(通常在实践中是这种情况),或者它们可以纯粹是概念性的 .
>>
运算符保证将这些虚拟位向右移位,这意味着它始终保证将正整数值除以2.因此,对于x = 42
的初始值,此x = x >> 1
保证在x
中产生21
. 这意味着如果某个机器在物理上表示42
为011011
,那么该机器的编译器将需要生成将42
的表示形式更改为21
(无论它是什么)的表示的代码,即使物理上后者看起来不像"right shifted"011011
模式 .