gpt4 book ai didi

c - 按位与符号字符

转载 作者:太空狗 更新时间:2023-10-29 15:27:02 27 4
gpt4 key购买 nike

我有一个文件,我已将其读入数据类型为 signed char 的数组。我无法改变这个事实。

我现在想这样做:!((c[i] & 0xc0) & 0x80) 其中 c[i] 是签名字符之一。

现在,我从 C99 standard 的第 6.5.10 节知道“[按位与] 的每个操作数都应具有整数类型。”

C99 规范的第 6.5 节告诉我:

Some operators (the unary operator ~ , and the binary operators << , >> , & , ^ , and | , collectively described as bitwise operators )shall have operands that have integral type. These operators return values that depend on the internal representations of integers, and thus have implementation-defined aspects for signed types.

我的问题有两个方面:

  • 由于我想使用文件中的原始位模式,如何将我的 signed char 转换/转换为 unsigned char 以便位模式保持不变?

  • 是否有这些“实现定义的方面”的列表(比如 MVSC 和 GCC)?

或者您可以采取不同的方式,并争辩说这对 c[i] 的任何值的有符号和无符号字符产生相同的结果。

自然地,我会奖励对相关标准或权威文本的引用,并阻止“知情”猜测。

最佳答案

正如其他人指出的那样,您的实现很可能是基于二进制补码的,并且会给出您期望的结果。

但是,如果您担心涉及有符号值的操作结果,并且您只关心位模式,只需直接转换为等效的无符号类型即可。结果在标准下定义:


6.3.1.3 有符号和无符号整数

  1. ...

  2. 否则,如果新类型是无符号的,则通过重复添加或转换值比新类型可以表示的最大值减一直到值在新类型的范围内。


这实质上是指定结果将是值的二进制补码表示。

其基本原理是,在二进制补码数学中,计算结果是对 2 的某个幂(即类型中的位数)取模,这又恰好等同于屏蔽掉相关位数。一个数的补数是从 2 的幂中减去的数。

因此,添加一个负值等同于添加任何与该值相差 2 的幂的倍数的值。

即:

        (0 + signed_value) mod (2^N)
==
(2^N + signed_value) mod (2^N)
==
(7 * 2^N + signed_value) mod (2^N)

等(如果你知道模数,那应该是不言而喻的)

因此,如果您有一个负数,加上 2 的幂将使它成为正数 (-5 + 256 = 251),但底部的“N”位将完全相同 (0b11111011),并且不会影响数学运算的结果。由于值随后会被截断以适合类型,因此即使结果“溢出”,结果也正是您所期望的二进制值(即,如果数字以正开头,您可能会认为会发生什么 - 这种包装也是定义明确的行为).

所以在 8 位二进制补码中:

  • -5 与 251 相同(即 256 - 5)- 0b11111011
  • 如果将 30 和 251 相加,将得到 281。但它大于 256,并且 281 mod 256 等于 25。与 30 - 5 完全相同。
  • 251 * 2 = 502.502 mod 256 = 246.246 和 -10 都是 0b11110110。

同样,如果您有:

unsigned int a;
int b;

a - b == a + (unsigned int) -b;

在幕后,这个转换不太可能用算术实现,并且肯定是从一个寄存器/值到另一个寄存器/值的直接赋值,或者只是完全优化掉,因为数学没有区分有符号和无符号(解释CPU 标志是另一回事,但这是一个实现细节)。该标准的存在是为了确保实现不会自己去做一些奇怪的事情,或者我想,对于一些不使用二进制补码的奇怪架构......

关于c - 按位与符号字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14233716/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com