操作符易错点<c语言学习>

左移操作符,右移操作符

        c语言中左移操作符和右移操作符不会改变操作数的值

在C语言中,左移操作符(<<)和右移操作符(>>)确实会改变它们操作数的值,但这个改变是针对它们所操作的变量而言。当执行如下的赋值操作时:

int a = some_value;
int b;
b = a << 1; // 左移操作

`a` 的值并不会直接因为 `b = a << 1` 这个表达式而改变,也就是说,`a` 原来的二进制表示不会因为给 `b` 赋值的过程而发生改变。

然而,`b` 的值会被改变为 `a` 左移一位后的结果。如果 `a` 的原始二进制形式是 `abcd...`,那么经过 `b = a << 1` 后,`b` 的值将是 `bcd...0`(高位丢弃,低位补0)。

同样地,对于右移操作符:

b = a >> 1; // 右移操作

此时 `b` 的值会被改变为 `a` 右移一位后的结果。根据有符号数还是无符号数以及具体编译器实现(算术移位或逻辑移位),移出的高位可能被原符号位填充(对于算术右移)或者填充0(对于逻辑右移)。而 `a` 的值依然保持不变。

总结一下,在上述例子中,`a` 的值不因移位运算符的操作而变化,而 `b` 的值则根据 `a` 的移位结果进行了相应改变。

        左移和右移操作的是整数的补码

        在C语言中,左移和右移操作符对整数的操作确实是以补码形式进行的。对于有符号整数而言:

- 左移操作(<<):将操作数的二进制表示向左移动指定的位数,左边移出的位通常被丢弃,右边空出的位置根据原数是正数还是负数以不同的方式填充。对于正数,右边空出的位通常用0填充;对于负数(补码形式下最高位为1),填充什么取决于编译器实现,一般会继续填充1(即保持负数不变)。

- 右移操作(>>):
  - 对于无符号整数,高位移出的位被舍弃,低位空出的位置一律用0填充。
  - 对于有符号整数,不同编译器有不同的实现:
    - 算术右移(arithmetic right shift):对于负数,高位移出的位会被复制到低位,保证移位后数值的符号不变;对于正数,则等同于无符号整数的逻辑右移。
    - 逻辑右移(logical right shift):无论正负数,高位移出的位均被舍弃,低位一律用0填充。这种行为在一些处理器或编译器中用于无符号整数,但在某些场合下也可能用于有符号整数。

        左移右移不能完全看做乘2或除2

        

        在使用补码表示的计算机系统(如Java和C语言)中,当一个正整数通过左移操作符(<<)向左移动时,如果移动的位数足够多,导致最高位(符号位)被1填充,则该数在解释时会被视为负数。

例如,假设我们有一个32位的正整数`int a = 1;`,其二进制表示为 `00000000 00000000 00000000 00000001`。如果我们将它左移31位:

a = a << 31;

结果会得到 `10000000 00000000 00000000 00000000`,这个二进制数在补码表示下会被解释为 `-2^31`,这是一个负整数。

需要注意的是,如果左移的位数超过了类型的最大位数(比如int类型的32位),超出部分通常会被丢弃,并且根据不同的编译器实现和标准,对于有符号整数的左移可能有不同的处理方式,但一般情况下不会因为左移而直接产生未定义行为,除非移动的位数是一个变量并且在运行时决定,这种情况下根据C/C++标准左移不确定数量的位是未定义行为。在实际编程中,应确保左移的位数合理以避免意外的结果或溢出问题。

区分按位与 按位或 按位异或 按位取反 逻辑或 逻辑与

1. **按位与(&)**
   - 符号:`&`
   - 功能:对两个操作数的每个对应位执行逻辑与操作。如果两个位都是1,则结果位为1;否则结果位为0。
   - 示例:
   


     int a = 6; // 二进制: 0110
     int b = 3; // 二进制: 0011
     int c = a & b; // 结果 c = 2 (二进制: 0010)

2. **按位或(|)**
   - 符号:`|`
   - 功能:对两个操作数的每个对应位执行逻辑或操作。如果至少有一个位是1,则结果位为1;如果两个位都是0,则结果位为0。
   - 示例:
 


     int a = 6; // 二进制: 0110
     int b = 3; // 二进制: 0011
     int c = a | b; // 结果 c = 7 (二进制: 0111)

3. **按位异或(^)**
   - 符号:`^`
   - 功能:对两个操作数的每个对应位执行逻辑异或操作。当两个位不相同时(一个为0另一个为1),结果位为1;当两个位相同(都为0或都为1)时,结果位为0。
   - 示例:

 
     int a = 6; // 二进制: 0110
     int b = 3; // 二进制: 0011
     int c = a ^ b; // 结果 c = 5 (二进制: 0101)

非常抱歉,您提到的“按位取反”操作也是非常重要的位运算符之一,我之前未包括在内。现在补充说明:

4. **按位取反(~)**
   - 符号:`~`
   - 功能:对一个操作数的每个位执行逻辑非操作。即将每个位变为相反的状态,即0变成1,1变成0。对于有符号整数,最高位(符号位)的反转会改变整个数值的正负性。
   - 示例:


     int a = 6; // 二进制: 0110
     int b = ~a; // 结果 b = -7 (二进制补码表示: 1001...1110)

在这个例子中,对整数6进行按位取反后得到的结果(以32位为例)是 `11111111 11111111 11111111 11111001`,这个值在补码表示下解释为-7。

5. **逻辑与(&&)**
   - 符号:`&&`
   - 功能:这是布尔逻辑运算符,用于判断表达式之间的逻辑关系。只有当两边的操作数都为真(非零)时,整个表达式的结果才为真(非零)。它不是针对单个位进行操作,而是针对整个表达式的值。
   - 示例:


     int a = 6;
     int b = 3;
     if (a > 0 && b > 0) {
         printf("Both values are positive.\n");
     }

6. **逻辑或(||)**
   - 符号:`||`
   - 功能:这也是布尔逻辑运算符,用于判断表达式之间的逻辑关系。只要两边的操作数中有任意一个为真(非零),则整个表达式的结果就为真(非零)。同样,它不作用于单个位,而是作用于整个表达式的值。
   - 示例:


     int a = 6;
     int b = -3;
     if (a > 0 || b > 0) {
         printf("At least one value is positive.\n");
     }

总结一下,前四种运算是按位操作,应用于整数类型的每一位上,而逻辑与和逻辑或运算是逻辑操作,应用于布尔表达式以判断整体条件是否满足。

        

  • 20
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值