C 无符号字符旋转

C 无符号字符旋转,c,rotation,twos-complement,unsigned-char,C,Rotation,Twos Complement,Unsigned Char,我有点搞不清楚什么是无符号字符。有符号字符是以位形式表示的字符,对吗?一个示例问题使我们向右旋转n位位置,即使用此解决方案的无符号字符的位: unsigned char rotate(unsigned char x, int n) { unsigned char temp = x << 8 - n; x = x >> n; return (x | temp); } unsigned char rotate(unsigned char x,int

我有点搞不清楚什么是无符号字符。有符号字符是以位形式表示的字符,对吗?一个示例问题使我们向右旋转n位位置,即使用此解决方案的无符号字符的位:

unsigned char rotate(unsigned char x, int n) {
    unsigned char temp = x << 8 - n;
    x = x >> n;
    return (x | temp);
}
unsigned char rotate(unsigned char x,int n){
无符号字符温度=x>n;
返回(x |温度);
}

如果有人能用字符示例及其各自的位来解释,我们将不胜感激。非常感谢。

将变量声明为
unsigned char
告诉编译器将底层位模式视为0(00000000)到255(11111111)之间的数字。将其声明为
char
会告诉编译器应用于底层位模式,并将其视为-128(10000000)到127(01111111)之间的数字

考虑一个3位数字。如果未签名,则您有:

000 = 0
001 = 1
010 = 2
011 = 3
100 = 4
101 = 5
110 = 6
111 = 7
100 = -4
101 = -3
110 = -2
111 = -1
000 =  0
001 =  1
010 =  2
011 =  3
如果已签署,则您有:

000 = 0
001 = 1
010 = 2
011 = 3
100 = 4
101 = 5
110 = 6
111 = 7
100 = -4
101 = -3
110 = -2
111 = -1
000 =  0
001 =  1
010 =  2
011 =  3
关于算术(正如该链接所提到的)最简洁的是,您不必将有符号二进制数与无符号二进制数区别对待。您只需进行实际的二进制计算,而不考虑有符号或无符号。但是您必须将有符号/无符号解释应用于输入和输出

在签名域中,您可能有:

2 + (-3) = 010 + 101 = 111 = -1
但在未签名领域,这是:

2 + 5 = 010 + 101 = 111 = 7

因此,这完全是一个解释问题,因为实际添加的位模式和总和的位模式在这两种情况下都是相同的。

将变量声明为
无符号字符
告诉编译器将底层位模式视为从0(00000000)到255(11111111)的数字。将其声明为
char
会告诉编译器应用于底层位模式,并将其视为-128(10000000)到127(01111111)之间的数字

考虑一个3位数字。如果未签名,则您有:

000 = 0
001 = 1
010 = 2
011 = 3
100 = 4
101 = 5
110 = 6
111 = 7
100 = -4
101 = -3
110 = -2
111 = -1
000 =  0
001 =  1
010 =  2
011 =  3
如果已签署,则您有:

000 = 0
001 = 1
010 = 2
011 = 3
100 = 4
101 = 5
110 = 6
111 = 7
100 = -4
101 = -3
110 = -2
111 = -1
000 =  0
001 =  1
010 =  2
011 =  3
关于算术(正如该链接所提到的)最简洁的是,您不必将有符号二进制数与无符号二进制数区别对待。您只需进行实际的二进制计算,而不考虑有符号或无符号。但是您必须将有符号/无符号解释应用于输入和输出

在签名域中,您可能有:

2 + (-3) = 010 + 101 = 111 = -1
但在未签名领域,这是:

2 + 5 = 010 + 101 = 111 = 7

因此,这完全是一个解释问题,因为添加的实际位模式和求和的位模式在这两种情况下都是相同的。

无符号字符只是一种8位整数类型,其值可以介于0和255之间,有符号字符的值可以介于-127和128之间。在实际的机器代码中,除了一个不同之外,没有什么真正的区别:当您使用>>(char、short或int)对有符号类型执行右移位时,它作为算术移位执行,这意味着对于负值(其MSB为1),将1移位,而不是0,并且上述代码将无法按预期工作

编辑:上面的代码示例将有符号字符和无符号字符旋转3位:

00110101旋转无符号和有符号为10100110

但对于前面有1的数字,你会得到一个算术移位,因此

11010001无符号旋转为00111010。

11010001旋转有符号字符是11111010。

无符号字符只是一种8位整数类型,其值可以介于0和255之间,有符号字符的值可以介于-127和128之间。在实际的机器代码中,除了一个不同之外,没有什么真正的区别:当您使用>>(char、short或int)对有符号类型执行右移位时,它作为算术移位执行,这意味着对于负值(其MSB为1),将1移位,而不是0,并且上述代码将无法按预期工作

编辑:上面的代码示例将有符号字符和无符号字符旋转3位:

00110101旋转无符号和有符号为10100110

但对于前面有1的数字,你会得到一个算术移位,因此

11010001无符号旋转为00111010。

11010001旋转有符号字符是11111010。

有符号字符
字符
无符号字符
都是整数类型。为了简单起见,我假设CHAR_位是8,有符号类型是2的补码。因此:

  • signed char
    是一个从-128到+127的数字
  • unsigned char
    是一个从0到255的数字
  • char
    signed char
    的范围相同,或者与
    unsigned char
    的范围相同,具体取决于您的C实现
就C而言,字符只是
char
类型范围内的一个数字(尽管各种字符函数如
tolower
要求在输入时将值转换为无符号类型,即使
char
是有符号的)

所以,
signed char
unsigned char
都是位形式的字符表示。对于0到+127范围内的数字,它们都使用相同的表示法(只有一种方法可以用二进制表示正数)。对于超出该范围的数字,负数
n
的有符号表示与
n+256
的无符号表示(2的补码定义)是相同的位

此代码使用无符号字符的原因是带有负符号值的右移位具有实现定义的结果。带负号值的左移位具有未定义的行为。通常,左移位的行为与无符号值的行为相同,这是正常的,但右移位在左侧插入值为1的位,即所谓的“算术移位”,这不是这里需要的。无符号值总是以零移位,正是零的移位使代码能够将旋转结果的两部分和/或它们一起构建

因此,假设输入值x=254(
11111110
),n=1,我们得到:

x << 7 is 0111111100000000
x >> 1 is         01111111
|      is 0111111101111111
convert to unsigned char to return is 01111111
那么位操作呢