我试图了解C
中按位运算符的工作方式,但是我对<<
运算符有误解。
我有以下代码:
#include <stdio.h>
int Add(int x, int y);
int Add(int x, int y)
{
while ( y != 0 ) /// Iterate till there is no carry
{
int carry = x & y; /// carry now contains common set bits of x and y
x = x ^ y; /// Sum of bits of x and y where at least one of the bits is not set
y = carry << 1; /// Carry is shifted by one so that adding it to x gives the required sum
}
return x;
}
int main( void )
{
printf( "%d", Add( 13, 17 ) );
return 0;
}
如果我正确理解的话,是这样的:
First Iteration:
|=======================================|
| |
| while ( y != 0 ) |
| while ( 17 != 0 ) |
| while ( 10001 != 00000 ) |
| |
| c = x & y; |
| 1 = 13 & 17 |
| 00001 = 01101 & 10001 |
| |
| x = x ^ y |
| 28 = 13 ^ 17 |
| 11100 = 01101 ^ 10001 |
| |
| y = c << 1 |
| 17 = 1 << 1 |
| 10001 = 00001 << 00001 |
| 00010 = 00001 << 00001 |
| |
|=======================================|
Second Iteration:
|=======================================|
| |
| while ( y != 0 ) |
| while ( 2 != 0 ) |
| while ( 00010 != 00000 ) |
| |
| c = x & y; |
| 0 = 28 & 2 |
| 00000 = 11100 & 00010 |
| |
| x = x ^ y |
| 30 = 28 ^ 2 |
| 11110 = 11100 ^ 00010 |
| |
| y = c << 1 |
| 2 = 0 << 1 |
| 00010 = 00000 << 00001 |
| 00000 = 00000 << 00001 |
| |
|=======================================|
然后Y
变成0
,X
返回30
。
现在在以下代码中我遇到了一个问题:
#include <stdio.h>
int main( void )
{
int x = 13;
int y = x << 1; /// 11010 = 01101 << 00001
x = 0 << 1; /// 00000 = 00000 << 00001
printf("y = %d\n", y ); /// 26 | 11010
printf("x = %d\n", x ); /// 26 | 11010
return 0;
}
如果我没看错,我们将所有位向左移一位。
int y = x << 1; /// 11010 = 01101 << 00001
但是这里到底发生了什么
x = 0 << 1; /// 00000 = 00000 << 00001
x
是否被清除并充满0 << 1
的结果?
答案 0 :(得分:0)
x是否被清除并填充0 << 1的结果?
x
仅被分配了表达式0 << 1
的值。左移或右移零都保持0
。
那么这意味着第一和第二迭代的表示是正确的吗?
是正确的,除了在以下情况下替换旧值变量(在lhs上)有点令人困惑。
17 = 1 << 1
10001 = 00001 << 00001
和
2 = 0 << 1
00010 = 00000 << 00001
将其描述为:
y = 1 << 1
y = 00001 << 00001
和
y = 0 << 1
y = 00000 << 00001
答案 1 :(得分:0)
n << k
is actually n * (2^k)
as long as you have enough bits available to keep all of the resulting bits. So 0 << k
is 0 * (2^k) = 0
whatever the (positive integer) value of k is.
Note that for usual 32 bit integers, a number on p = 17
bits or more, like 65537 (0x0001_0001)
, will stop behaving like the multiplication once k is greater or equal to (32+1)-p = (32+1)-17 = 16
, as for example 65537 << 16
is 0x1_0001_0000
which is using 33 bits and is truncated to 0x0001_0000 = 65536
.
With 65536 << 15
you may also start having strange results as the result, 0x1000_0000
, is changing the left most bit, which is the sign bit if you're not using unsigned values...