简体   繁体   English

如何在不丢失位的情况下执行c的移位?

[英]how do I perform shifts in c without losing bits?

In C when you do something like this: 在C中你做这样的事情:

char var = 1;

while(1)
{
  var = var << 1;
}

In the 8th iteration the "<<" operator will shift out the 1 and var will be 0. I need to perform a shift in order to mantain the bit shifting. 在第8次迭代中,“<<”运算符将移出1并且var将为0.我需要执行移位以保持位移位。 In other words I need this: 换句话说,我需要这个:

initial ----- 00000001 首字母----- 00000001

1st shift -- 00000010 第一班 - 00000010

2nd shift - 00000100 第二班 - 00000100

3rd shift - 00001000 第3班 - 00001000

4th shift - 00010000 第四班 - 00010000

5th shift -- 00100000 第五班 - 00100000

6th shift -- 01000000 第6班 - 01000000

7th shift - 10000000 第7班 - 10000000

8th shift - 00000001 (At the 8th shift the one automatically start again) 第8班 - 00000001(第8班,自动重启)

Is there something equivalent to "<<" but to achieve this? 有没有相当于“<<”的东西,但实现这一点?

This is known as a circular shift , but C doesn't offer this functionality at the language level. 这称为循环移位 ,但C在语言级别不提供此功能。

You will either have to implement this yourself, or resort to inline assembler routines, assuming your platform natively has such an instruction. 您要么必须自己实现,要么采用内联汇编程序例程,假设您的平台本身具有此类指令。

For example: 例如:

var = (var << 1) | (var >> 7);

(This is not well-defined for negative signed types, though, so you'd have to change your example to unsigned char .) (但是,对于负面signed类型,这没有明确定义,因此您必须将示例更改为unsigned char 。)

Yes, you can use a circular shift . 是的,你可以使用循环班次 (Although it isn't a built-in C operation, but it is a CPU instruction on x86 CPUs) (虽然它不是内置的C操作,但它是x86 CPU上的CPU指令

So you want to do a bit rotation, aka circular shift, then. 所以你想做一点旋转,也就是循环移位。

#include <limits.h>   // Needed for CHAR_BIT

// positive numbits -> right rotate, negative numbits -> left rotate
#define ROTATE(type, var, numbits) ((numbits) >= 0 ? \
                                    (var) >> (numbits) | (var) << (CHAR_BIT * sizeof(type) - (numbits)) : \
                                    (var) << -(numbits) | (var) >> (CHAR_BIT * sizeof(type) + (numbits)))

As sizeof() returns sizes as multiples of the size of char ( sizeof(char) == 1 ), and CHAR_BIT indicates the number of bits in a char (which, while usually 8, won't necessarily be), CHAR_BIT * sizeof(x) will give you the size of x in bits. 由于sizeof()返回大小为charsizeof(char) == 1 )大小的倍数,而CHAR_BIT表示char的位数(虽然通常为8,但不一定是), CHAR_BIT * sizeof(x)将以比特为单位给出x的大小。

This is called a circular shift. 这称为循环移位。 There are intel x86 assembly instructions to do this but unless performance is REALLY REALLY A HUGE ISSUE you're better off using something like this: 有这样做的英特尔x86汇编指令,但除非性能真是一个巨大的问题,你最好使用这样的东西:

int i = 0x42;
int by = 13;
int shifted = i << by | i >> ((sizeof(int) * 8) - by);

If you find yourself really needing the performance, you can use inline assembly to use the instructions directly (probably. I've never needed it badly enough to try). 如果你发现自己真的需要性能,你可以使用内联汇编直接使用说明(可能。我从来没有非常需要它尝试)。

It's also important to note that if you're going to be shifting by more places than the size of your data type, you need additional checks to make sure you're not overshifting. 同样重要的是要注意,如果您要移动的位置超过数据类型的大小,则需要进行额外检查以确保不会过度移位。 Using by = 48 would probably result in shifted receiving a value of 0, though this behavior may be platform specific (ie something to avoid like the plague) because if I recall correctly, some platforms perform this masking automatically and others do not. 使用by = 48可能会导致移位接收值为0,尽管此行为可能是特定于平台的(即可能像瘟疫一样避免),因为如果我没记错,某些平台会自动执行此屏蔽而其他平台则不会。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM