开始时右移零 [英] Right shift with zeros at the beginning

查看:55
本文介绍了开始时右移零的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试一种左移操作,该操作会在开头添加零而不是一个零.例如,如果我左移 0xff ,我会得到:

I'm trying to do a kind of left shift that would add zeros at the beginning instead of ones. For example, if I left shift 0xff, I get this:

0xff << 3 = 11111000

但是,如果我右移它,我会得到:

However, if I right shift it, I get this:

0xff >> 3 = 11111111

我可以使用任何操作来获得与左移等效的操作吗?即,我想得到这个:

Is there any operation I could use to get the equivalent of a left shift? i.e. I would like to get this:

00011111

有什么建议吗?

修改

要回答评论,这是我正在使用的代码:

To answer the comments, here is the code I'm using:

int number = ~0;
number = number << 4;   
std::cout << std::hex << number << std::endl;

number = ~0;
number = number >> 4;
std::cout << std::hex << number << std::endl;

输出:

fffffff0
ffffffff

由于似乎总体上它应该可以工作,所以我对为什么此特定代码不起作用很感兴趣.有什么主意吗?

Since it seems that in general it should work, I'm interested as to why this specific code doesn't. Any idea?

推荐答案

这是C语言和二进制算术两者共同起作用的方式:

This is how C and binary arithmetic both work:

如果您左移 0xff<<3 ,您将获得二进制文件: 00000000 11111111<<3 = 00000111 11111000

If you left shift 0xff << 3, you get binary: 00000000 11111111 << 3 = 00000111 11111000

如果您右移 0xff>>3 ,您将获得二进制文件: 00000000 11111111>>3 = 00000000 00011111

If you right shift 0xff >> 3, you get binary: 00000000 11111111 >> 3 = 00000000 00011111

0xff 是一个带正数 255 的(带符号)整数.由于它是肯定的,因此在C和C ++中,将其转移的结果都是明确定义的行为.它不会进行任何算术移位,也不会进行任何种类或定义不明确的行为.

0xff is a (signed) int with the positive value 255. Since it is positive, the outcome of shifting it is well-defined behavior in both C and C++. It will not do any arithmetic shifts nor any kind or poorly-defined behavior.

#include <stdio.h>

int main()
{

  printf("%.4X %d\n", 0xff << 3, 0xff << 3);
  printf("%.4X %d\n", 0xff >> 3, 0xff >> 3);

}

输出:

07F8 2040
001F 31

因此您在程序中执行了一些奇怪的操作,因为它无法按预期运行.也许您正在使用char变量或C ++字符文字.

So you are doing something strange in your program because it doesn't work as expected. Perhaps you are using char variables or C++ character literals.

来源:ISO 9899:2011 6.5.7.

Source: ISO 9899:2011 6.5.7.

问题更新后进行编辑

int number =〜0; 给出一个等于-1的负数,假定为2的补码.

int number = ~0; gives you a negative number equivalent to -1, assuming two's complement.

number =数字<<4; 调用未定义的行为,因为您左移了一个负数.该程序正确地执行了未定义的行为,因为它不执行任何操作或根本不执行任何操作.它可能会打印fffffff0或可能会打印粉红色的大象,或者可能会格式化硬盘驱动器.

number = number << 4; invokes undefined behavior, since you left shift a negative number. The program implements undefined behavior correctly, since it either does something or nothing at all. It may print fffffff0 or it may print a pink elephant, or it may format the hard drive.

number = number>>4; 调用实现定义的行为.在您的情况下,编译器会保留符号位.这称为算术移位,算术右移以填充MSB的方式工作移位之前具有的任何比特值.因此,如果您的数字为负数,您将体验到该程序正在移入".

number = number >> 4; invokes implementation-defined behavior. In your case, your compiler preserves the sign bit. This is known as arithmetic shift, and arithmetic right shift works in such a way that the MSB is filled with whatever bit value it had before the shift. So if you have a negative number, you will experience that the program is "shifting in ones".

在所有现实世界中有99%的情况下,对带符号的数字使用按位运算符是没有意义的.因此,请始终确保使用无符号数,并且C/C ++中没有任何危险的隐式转换规则会将其转换为有符号的数字(有关危险转换的更多信息,请参见整数提升规则"和通常的算术转换").,有关SO方面的大量好信息).

In 99% of all real world cases, it doesn't make sense to use bitwise operators on signed numbers. Therefore, always ensure that you are using unsigned numbers, and that none of the dangerous implicit conversion rules in C/C++ transforms them into signed numbers (for more info about dangerous conversions, see "the integer promotion rules" and "the usual arithmetic conversions", plenty of good info about those on SO).

编辑2 ,来自C99标准的基本文档V5.10的一些信息:

EDIT 2, some info from the C99 standard's rationale document V5.10:

6.5.7按位移位运算符

6.5.7 Bitwise shift operators

在K& R中对移位运算符的描述表明,移位a长计数应强制将左操作数扩宽到很久之前被转移.C89认可的更直观的做法委员会,是班次计数的类型与结果的类型.

The description of shift operators in K&R suggests that shifting by a long count should force the left operand to be widened to long before being shifted. A more intuitive practice, endorsed by the C89 Committee, is that the type of the shift count has no bearing on the type of the result.

C89的静音更改

长时间移位不会再将移位后的操作数强制转换为长.C89委员会确认给予实施的自由由K& R提出,不要求已签名的右移操作进行签名扩展,因为这样的要求可能会减慢快速代码的速度,并且标志扩展移位的用处很小.(移动一个负二的补码整数在算术上正确的一位是不等于被二除!)

Shifting by a long count no longer coerces the shifted operand to long. The C89 Committee affirmed the freedom in implementation granted by K&R in not requiring the signed right shift operation to sign extend, since such a requirement might slow down fast code and since the usefulness of sign extended shifts is marginal. (Shifting a negative two’s complement integer arithmetically right one place is not the same as dividing by two!)

这篇关于开始时右移零的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆