C/c++中移位与负数表达的一点研究

本文探讨了移位操作中的常见问题,包括左移和右移的不同效果、符号位处理方式及其与编译器的关系,并分析了在不同位数下整数表示的变化。

    最近在项目开发过程中,遇到一些移位问题和有符号无符号转换时的表达问题,造成了种种的困惑。所以,个人抽出一点时间与之做了个彻底的了断。废话少说。切入正题.

    来看一下代码:

    

int _tmain(int argc, _TCHAR* argv[])
{
	char ch = 0x13;
	int value = ch << 8;
	value = ch << 16;
	value = ch << 24;
	value = ch << 32;

	return 0;
}


    你能说出每一步的value的值吗?

     笔者之前一直认为,移位操作,左移就是将位左移,右补0;右移就是将位右移,左补零.(其中涉及算数移位与逻辑移位)。逻辑移位就是不考虑符号位,而算术移位需要考虑符号位.但是在将char左移32位时,预想的结果为0,但实际上是0x13.发生了循环移位,其并未丢掉移除的位进行补零操作。这与编译器有关吗?往达人指点.

    总结几点:(1)移位操作 若不强制设定类型 默认为int  上例中会将ch转换为int

    (2)移位过程中 若超出了int的范围 例如移位32为 则会发生循环移位 目前不确定是否与编译器有关

   (3)有时根据需要需要考虑算术与逻辑移位操作

 

以上是移位  再看下面的负数表达问题

int _tmain(int argc, _TCHAR* argv[])
{
	char ch = 0x13;
	int value = ch << 8;
	value = ch << 16
	value = ch << 24;
	value = ch << 32;

	__int64 l_value = ch << 62;
	__int64 l_value_0 = -0x4000000;

	return 0;
}


其中 ch << 62位后 其值为0xc0000000  由于是按照int解析 所以其值 = -0x4000000  该值赋予__int64时 最高符号位为1 求反码后+1 最终得到0xffffffffc0000000;

l_value与l_value_0的值是相等的.

 

 

<think>我们被要求详细解释C/C++中的位运算及其使用方法。根据用户提供的引用[1]中已经包含了一部分位运算的内容,我们将在此基础上扩展,形成一个完整的位运算详解。 位运算包括:按位(&)、按位或(|)、按位异或(^)、按位取反(~)、左移(<<)、右移(>>)。 我们将按照以下结构组织: 1. 按位(&) 2. 按位或(|) 3. 按位异或(^) 4. 按位取反(~) 5. 左移(<<) 6. 右移(>>) 7. 位运算的常见应用场景(结合示例) 注意:用户提供的引用[1]中已经有一些按位和按位或的例子,我们将整合并扩展。 另外,引用[2]是关于卷积算法的,运算无关,因此我们忽略。 开始详细解释:</think>### C/C++运算详解及使用示例 位运算直接操作整数的二进制位,是底层开发、嵌入式系统和性能优化中的核心操作。以下是六大位运算符的完整解析及实践案例: --- #### 一、基础位运算符 | 运算符 | 名称 | 规则描述 | 示例(二进制) | |--------|------------|------------------------------|------------------------| | `&` | 按位 | 同1为1,否则为0 | `1100 & 1010 = 1000` | | `\|` | 按位或 | 有1为1,同0为0 | `1100 \| 1010 = 1110` | | `^` | 按位异或 | 相同为0,不同为1 | `1100 ^ 1010 = 0110` | | `~` | 按位取反 | 0变1,1变0(一元操作) | `~1100 = 0011` | | `<<` | 左移 | 高位丢弃,低位补0 | `1100 << 2 = 110000` | | `>>` | 右移 | 低位丢弃,高位补符号位(有符号数)或0(无符号数) | `1100 >> 2 = 0011` | --- #### 二、关键特性运算律 1. **特殊值规则** - `a & 0 = 0`:任何数0按位结果为0[^1] ```cpp int a = 5; // 0101 int b = a & 0; // b = 0 ``` - `a & 1 = a的最低位`:提取末位(奇偶判断)[^1] ```cpp int num = 7; // 0111 bool isOdd = num & 1; // isOdd = true (1) ``` 2. **恒等归零律** - `a & a = a`:自身运算不变 - `a & (~a) = 0`:互补掩码归零[^1] - `a ^ a = 0`:自身异或归零 - `a ^ 0 = a`:0异或保持不变 3. **交换律结合律** ```cpp a ^ b = b ^ a // 异或交换律 (a ^ b) ^ c = a ^ (b ^ c) // 异或结合律 ``` --- #### 三、实践应用场景代码示例 ##### 1. 权限控制系统(位掩码) ```cpp enum Permissions { READ = 1 << 0, // 0001 WRITE = 1 << 1, // 0010 EXECUTE = 1 << 2 // 0100 }; int userA = READ | WRITE; // 0011 (3) bool canWrite = userA & WRITE; // true (0010 & 0011 = 0010 ≠ 0) ``` ##### 2. 高效数值交换(无临时变量) ```cpp int x = 10, y = 20; x ^= y; // x = x ^ y y ^= x; // y = y ^ (x ^ y) = x x ^= y; // x = (x ^ y) ^ x = y // 结果:x=20, y=10 ``` ##### 3. 快速乘除2的幂(移位优化) ```cpp int n = 8; int doubled = n << 1; // 16 (乘2) int halved = n >> 1; // 4 (除2) ``` ##### 4. 提取特定位域 ```cpp uint32_t color = 0xFF3366; // RGB: 0xRRGGBB uint8_t green = (color >> 8) & 0xFF; // 提取G分量 (0x33) ``` ##### 5. 奇偶性高效判断 ```cpp bool isEven(int n) { return (n & 1) == 0; // 末位为0即为偶数 } ``` --- #### 四、进阶技巧注意事项 1. **符号位处理** ```cpp int a = -8; // 补码: 1111...1000 int b = a >> 1; // 算术右移: 1111...1100 (-4) unsigned c = a >> 1; // 逻辑右移: 0111...1100 (巨大正数) ``` 2. **未定义行为规避** - 避免负数的左移:`(-1) << 1` 结果未定义 - 移位超出位数:`a >> 32`(若`int`为32位)未定义 3. **复合位运算优化** ```cpp // 判断是否为2的幂 bool isPowerOfTwo(int n) { return n > 0 && (n & (n - 1)) == 0; } ``` 4. **位域结构体(内存优化)** ```cpp struct PackedData { unsigned flag1 : 1; // 1位存储 unsigned flag2 : 3; // 3位存储(0-7) }; ``` --- #### 五、性能对比(位运算 vs 算术运算) | 操作 | 算术运算 | 位运算 | 加速比 | |-------------|-------------|---------------|-------| | 乘2 | `a * 2` | `a << 1` | 3-5倍 | | 除2(整数) | `a / 2` | `a >> 1` | 4-6倍 | | 奇偶判断 | `a % 2 == 0`| `(a & 1) == 0`| 10倍+ | > 💡 **最佳实践** > - 优先用 `unsigned` 类型避免符号位干扰 > - 复杂表达式加括号明确优先级(如 `(a << 1) + 1`) > - 关键路径代码用位运算替代乘除 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值