交换C中的数字位

在C访谈中,我被要求将最后4位的数字的前4位交换掉。 (例如,1011 1110应为1110 1011.)

有人有解决方案吗?

如果你还没有看到或做过多少工作,一个很好的学习资源是:

  • 比特扭曲黑客
unsigned char c; c = ((c & 0xf0) >> 4) | ((c & 0x0f) << 4); 

这种面试问题没有“正确答案”。 有几种方法可以做到这一点(查找表,任何人?),并且需要讨论每种方式之间的权衡(可读性与性能对可移植性与可维护性之间的权衡)。

问题只是让你讨论上述一些问题的开场白,并确定你可以“深入”讨论这些问题。

只需使用一个临时变量并将最后一位移入该变量,然后在该方向上移位该位并在tmp var中的位中结束屏蔽,您就完成了。


更新:让我们添加一些代码,然后您可以选择更具可读性的代码。

工作一个class轮

 unsigned int data = 0x7654; data = (data ^ data & 0xff) | ((data & 0xf) << 4) | ((data & 0xf0) >> 4); printf("data %x \n", data); 

相同的代码但有一些tmp变量

 unsigned int data = 0x7654; unsigned int tmp1 = 0; unsigned int tmp2 = 0; tmp1 = (0x0f&data)<<4; tmp2 = (0xf0&data)>>4; tmp1 = tmp1 | tmp2; data = data ^ (data & 0xff); data = data | tmp1; printf("data %x \n", data); 

好吧,无论如何,一个class轮更短:)


更新:

如果你看一下gcc用-Os -S生成的asm代码,我的猜测是它们或多或少相同,因为在“编译器优化”部分中删除了开销。

不需要临时变量,这样的事情应该这样做:

 x = ((x & 0xf) << 4) | ((x & 0xf0) >> 4); 

根据x的确切类型,存在潜在的缺陷。 识别这个问题留给读者练习。

C ++ – 类似伪代码(可以很容易地重写为不使用临时变量):

 int firstPart = source & 0xF; int offsetToHigherPart = sizeof( source ) * CHAR_BIT - 4; int secondPart = ( source >> offsetToHigherPart ) & 0xF; int maskToSeparateMiddle = -1 & ( ~0xF ) & ( ~( 0xF << offsetToHigherPart ); int result = ( firstPart << offsetToHigherPart ) | secondPart | (source & maskToSeparateMiddle); 

这将需要定义CHAR_BIT。 它通常在limits.h中,并且被定义为8位,但严格来说是与平台相关的,并且在头文件中根本不能定义。

 unsigned char b; b = (b << 4) | (b >> 4); 

x86程序集:

 asm{ mov AL, 10111110b rol AL rol AL rol AL rol AL } 

http://www.geocities.com/SiliconValley/Park/3230/x86asm/asml1005.html

您是否正在寻找比标准位移更聪明的东西?

(假设a是8位类型)

 a = ((a >> 4) & 0xF) + ((a << 4) &0xF0) 

最简单的是(t是无符号):

 t = (t>>4)|(t<<4); 

但是如果你想混淆你的代码,或者交换其他位组合你可以使用这个基数:

 mask = 0x0F & (t ^ (t >> 4)); t ^= (mask | (mask << 4)); 
 /*swaping four bits*/ #include void printb(char a) { int i; for( i = 7; i >= 0; i--) printf("%d", (1 & (a >> i))); printf("\n"); } int swap4b(char a) { return ( ((a & 0xf0) >> 4) | ((a & 0x0f) << 4) ); } int main() { char a = 10; printb(a); a = swap4b(a); printb(a); return 0; } 

这是完全交换位的方法,用于更改字节中的位字节序。

“iIn”实际上是一个整数,因为我用它来读取文件。 我需要顺序中的位,我可以按顺序轻松读取它们。

 // swap bits iIn = ((iIn>>4) & 0x0F) | ((iIn<<4) & 0xF0); // THIS is your solution here. iIn = ((iIn>>2) & 0x33) | ((iIn<<2) & 0xCC); iIn = ((iIn>>1) & 0x55) | ((iIn<<1) & 0xAA); 

为了在单个字节中交换两个半字节,这是最有效的方法,在大多数情况下它可能比查找表更快。

我看到很多人在做转移,忘了在这里做掩饰。 当有符号扩展时,这是一个问题。 如果你有unsigned char的类型,那很好,因为它是一个无符号的8位数量,但是它会因任何其他类型而失败。

掩码不会增加开销,使用unsigned char,无论如何隐含掩码,任何体面的编译器都会删除不必要的代码并且有20年的时间。

通用n位在最后和第一位之间交换的解决方案。 当总位小于2n时未validation。 这里7是char,31是整数。

 unsigned char swapNbitsFtoL(unsigned char num, char nbits) { unsigned char u1 = 0; unsigned char u2 = 0; u1 = ~u1; u1 &= num; u1 = (u1 >> (7 - (nbits - 1))); /* Here nbits is number of n=bits so I have taken (nbits - 1). */ u2 = ~u2; u2 &= num; u2 = (u2 << (7 - (nbits - 1))); /* Here nbits is number of n=bits so I have taken (nbits - 1). */ u1 |= u2; /* u1 have first and last swapped n bits with */ u2 = 0; u2 = ~u2; u2 = ((u2 >> (7 - (nbits - 1))) | (u2 << (7 - (nbits - 1)))); bit_print(u2); u2 = ~u2; u2 &= num; return (u1 | u2); } 

我在这方面的技能是新的,因此未经证实,所以如果我错了,那么我会学到新东西,这至少是Stack Overflow的一部分。

bitmask和XOR也能工作吗?

像这样?

 var orginal= var mask =00001110 //I may have the mask wrong var value=1011 1110 var result=value^mask; 

我可能会误解事情,请原谅我,如果我搞砸了。

 #include  #include  #include  void main() { int q,t,n,a[20],j,temp; int i=0; int s=0; int tp=0; clrscr(); printf("\nenter the num\n"); scanf("%d",&n); t=n; while(n>0) { a[i]=n%2; i++; n=n/2; } printf("\n\n"); printf("num:%d\n",t); printf("number in binary format:"); for(j=i-1;j>=0;j--) { printf("%d",a[j]); } printf("\n"); temp=a[i-1]; a[i-1]=a[0]; a[0]=temp; printf("number in binary format wid reversed boundary bits:"); for(j=i-1;j>=0;j--) { printf("%d",a[j]); } printf("\n"); q=i-1; while(q>=0) { tp=pow(2,q); s=s+(tp*a[q]); q--; } printf("resulatnt number after reversing boundary bits:%d",s); printf("\n"); getch(); }