C语言 - 左移、右移运算符

C语言中的左移和右移运算符

左移(<<)和右移(>>)运算符是C语言中对二进制位进行移动的操作符。让我用最简单的方式解释给你听。

1. 基本概念:把二进制位想象成排队的人

想象二进制数就像一排人,每个人代表一个二进制位(0或1):

text
数字 13 的二进制:1 1 0 1
位置:             第3人 第2人 第1人 第0人

2. 左移运算符 <<

左移就是把所有位向移动,右边补0。

语法:

c
结果 = 数字 << 移动位数;

例子:

c
int a = 13;      // 二进制: 1101
int b = a << 1;  // 左移1位

移动过程:

text
原始:   1 1 0 1
左移1位: 1 1 0 1 0  (所有位向左移1位,右边补1个0)
结果:   1 1 0 1 0 = 26 (十进制)

实际效果:

  • 左移1位 ≈ 乘以2

  • 左移n位 ≈ 乘以2^n

c
13 << 1 = 26  (13 × 2 = 26)
13 << 2 = 52  (13 × 4 = 52)  
13 << 3 = 104 (13 × 8 = 104)

3. 右移运算符 >>

右移就是把所有位向移动,左边补0(正数)或补1(负数)。

语法:

c
结果 = 数字 >> 移动位数;

例子:

c
int a = 13;      // 二进制: 1101
int b = a >> 1;  // 右移1位

移动过程:

text
原始:   1 1 0 1
右移1位: 0 1 1 0  (最右边1被挤掉,左边补0)
结果:   0 1 1 0 = 6 (十进制)

实际效果:

  • 右移1位 ≈ 除以2(取整)

  • 右移n位 ≈ 除以2^n(取整)

c
13 >> 1 = 6   (13 ÷ 2 = 6.5 → 取整6)
13 >> 2 = 3   (13 ÷ 4 = 3.25 → 取整3)
13 >> 3 = 1   (13 ÷ 8 = 1.625 → 取整1)

4. 完整示例代码

c
#include <stdio.h>

// 打印二进制形式的函数
void printBinary(int num) {
    for (int i = 31; i >= 0; i--) {
        printf("%d", (num >> i) & 1);
        if (i % 4 == 0) printf(" "); // 每4位加空格,方便阅读
    }
}

int main() {
    int number = 13;
    
    printf("原始数字: %d\n", number);
    printf("二进制: ");
    printBinary(number);
    printf("\n\n");
    
    // 左移示例
    printf("=== 左移运算 ===\n");
    for (int i = 1; i <= 3; i++) {
        int result = number << i;
        printf("%d << %d = %d\n", number, i, result);
        printf("二进制: ");
        printBinary(result);
        printf("\n");
    }
    
    printf("\n=== 右移运算 ===\n");
    for (int i = 1; i <= 3; i++) {
        int result = number >> i;
        printf("%d >> %d = %d\n", number, i, result);
        printf("二进制: ");
        printBinary(result);
        printf("\n");
    }
    
    return 0;
}

5. 运行结果示例

text
原始数字: 13
二进制: 0000 0000 0000 0000 0000 0000 0000 1101 

=== 左移运算 ===
13 << 1 = 26
二进制: 0000 0000 0000 0000 0000 0000 0001 1010 
13 << 2 = 52
二进制: 0000 0000 0000 0000 0000 0000 0011 0100 
13 << 3 = 104
二进制: 0000 0000 0000 0000 0000 0000 0110 1000 

=== 右移运算 ===
13 >> 1 = 6
二进制: 0000 0000 0000 0000 0000 0000 0000 0110 
13 >> 2 = 3
二进制: 0000 0000 0000 0000 0000 0000 0000 0011 
13 >> 3 = 1
二进制: 0000 0000 0000 0000 0000 0000 0000 0001 

6. 特殊情况说明

负数的情况:

c
int a = -13;
int b = a >> 1;  // 对于负数,左边补1而不是0

边界情况:

c
int a = 1;
int b = a << 31; // 可能溢出,得到负数

7. 实际应用场景

快速乘除法:

c
// 比乘法快
int fastMultiplyBy4 = num << 2;    // num × 4
int fastDivideBy8 = num >> 3;      // num ÷ 8

位掩码操作:

c
// 检查第3位是否为1
if (value & (1 << 3)) {
    printf("第3位是1\n");
}

// 设置第5位为1
value = value | (1 << 5);

// 清除第2位
value = value & ~(1 << 2);

8. 重要注意事项

  1. 移位位数不能为负数a << -1 是未定义行为

  2. 移位位数不能超过数据类型位数:对于32位int,不要 a << 32

  3. 有符号数的右移:结果取决于编译器实现(算术右移或逻辑右移)

  4. 溢出问题:左移可能导致数值溢出变成负数

记忆口诀:

  • 左移:往左走,尾巴补零,数值变大(×2)

  • 右移:往右走,脑袋补零,数值变小(÷2)

现在你应该对C语言中的左移和右移运算符有了清晰的理解!它们本质上就是在二进制层面上移动位的位置。

 
 
 
 
 
 
 
 
 
 
 
 
再举一个例子吧 假如二进制数:1001, 左移动和右移怎么处理的
 
 
 
 
 
 
 

我们以二进制数1001(十进制9)为例,分别进行左移和右移操作。
注意:我们假设这个二进制数在一个至少4位的系统中,但实际在C语言中,我们通常处理的是整型,比如32位。
为了简单起见,我们先考虑4位的情况,然后扩展到8位或32位。

原始二进制: 1001 (十进制9)

左移操作(<<):
左移1位:所有位向左移动一位,最左边一位移出,最右边补0。
1001 左移1位 -> 10010 (注意,现在有5位了,但在计算机中,我们固定位数,比如8位,则表示为00010010)
在4位系统中,左移1位后,我们只取4位,则0010(十进制2),但实际在C语言中,我们是用整型,所以不会截断为4位。

在C语言中,我们通常用整型(比如32位)来存储数字。所以:
9的32位二进制表示:00000000 00000000 00000000 00001001
左移1位:00000000 00000000 00000000 00010010 -> 十进制18

右移操作(>>):
右移1位:所有位向右移动一位,最右边一位移出,最左边补0(对于无符号数)或补符号位(对于有符号数)。
我们以无符号数为例:9的二进制1001,右移1位 -> 0100(十进制4)
在32位中,9的二进制表示右移1位:00000000 00000000 00000000 00000100 -> 十进制4

注意:如果是有符号数,且是负数,右移补1。但9是正数,所以补0。

下面我们用代码演示:

 

二进制数 1001 的左移和右移详解

让我们用二进制数 1001 作为例子,详细演示左移和右移的操作过程。

1. 首先确定原始数值

二进制 1001 转换为十进制:

text
1    0    0    1
↓    ↓    ↓    ↓
2^3  2^2  2^1  2^0
8    0    0    1
总和 = 8 + 0 + 0 + 1 = 9

所以:二进制 1001 = 十进制 9

2. 左移操作 (<<)

左移1位:1001 << 1

操作过程:

text
原始:   1 0 0 1
左移1位: 1 0 0 1 0  (所有位向左移动1位,右边补1个0)
结果:   1 0 0 1 0

数值计算:

  • 原始:1001 = 9

  • 左移1位后:10010 = 16 + 2 = 18

  • 验证:9 × 2 = 18 ✓

左移2位:1001 << 2

操作过程:

text
原始:     1 0 0 1
左移2位: 1 0 0 1 0 0  (所有位向左移动2位,右边补2个0)
结果:     1 0 0 1 0 0

数值计算:

  • 左移2位后:100100 = 32 + 4 = 36

  • 验证:9 × 4 = 36 ✓

左移3位:1001 << 3

操作过程:

text
原始:       1 0 0 1
左移3位: 1 0 0 1 0 0 0  (所有位向左移动3位,右边补3个0)
结果:       1 0 0 1 0 0 0

数值计算:

  • 左移3位后:1001000 = 64 + 8 = 72

  • 验证:9 × 8 = 72 ✓

3. 右移操作 (>>)

右移1位:1001 >> 1

操作过程:

text
原始:   1 0 0 1
右移1位: 0 1 0 0  (所有位向右移动,左边补0,最右边1被丢弃)
结果:   0 1 0 0

数值计算:

  • 原始:1001 = 9

  • 右移1位后:0100 = 4

  • 验证:9 ÷ 2 = 4.5 → 取整4 ✓

右移2位:1001 >> 2

操作过程:

text
原始:     1 0 0 1
右移2位: 0 0 1 0  (所有位向右移动2位,左边补2个0,最右边2位被丢弃)
结果:     0 0 1 0

数值计算:

  • 右移2位后:0010 = 2

  • 验证:9 ÷ 4 = 2.25 → 取整2 ✓

右移3位:1001 >> 3

操作过程:

text
原始:       1 0 0 1
右移3位: 0 0 0 1  (所有位向右移动3位,左边补3个0,最右边3位被丢弃)
结果:       0 0 0 1

数值计算:

  • 右移3位后:0001 = 1

  • 验证:9 ÷ 8 = 1.125 → 取整1 ✓

4. C语言代码验证

c
#include <stdio.h>

// 打印二进制形式的函数(只显示低8位)
void printBinary(int num) {
    for (int i = 7; i >= 0; i--) {
        printf("%d", (num >> i) & 1);
        if (i % 4 == 0) printf(" ");
    }
}

int main() {
    int number = 0b1001;  // C语言中0b前缀表示二进制数
    
    printf("原始数字: %d\n", number);
    printf("二进制: ");
    printBinary(number);
    printf("\n\n");
    
    // 左移示例
    printf("=== 左移运算 ===\n");
    for (int i = 1; i <= 3; i++) {
        int result = number << i;
        printf("%d << %d = %d\n", number, i, result);
        printf("二进制: ");
        printBinary(result);
        printf("\n");
    }
    
    printf("\n=== 右移运算 ===\n");
    for (int i = 1; i <= 3; i++) {
        int result = number >> i;
        printf("%d >> %d = %d\n", number, i, result);
        printf("二进制: ");
        printBinary(result);
        printf("\n");
    }
    
    return 0;
}

5. 运行结果

text
原始数字: 9
二进制: 0000 1001 

=== 左移运算 ===
9 << 1 = 18
二进制: 0001 0010 
9 << 2 = 36
二进制: 0010 0100 
9 << 3 = 72
二进制: 0100 1000 

=== 右移运算 ===
9 >> 1 = 4
二进制: 0000 0100 
9 >> 2 = 2
二进制: 0000 0010 
9 >> 3 = 1
二进制: 0000 0001 

6. 重要观察

左移时的现象:

  • 每左移1位,数值翻倍(乘以2)

  • 如果最高位的1被移出数据范围,就会发生溢出

右移时的现象:

  • 每右移1位,数值减半(除以2,取整)

  • 移出的低位信息永久丢失

边界情况:

c
// 如果继续右移
9 >> 4 = 0  // 0000 0000,所有有效位都被移出了

// 如果左移太多导致溢出
9 << 4 = 144  // 1001 0000 = 128 + 16 = 144

7. 实际应用举例

快速计算:

c
// 快速计算 9 × 5
int result = (9 << 2) + 9;  // 9×4 + 9×1 = 36 + 9 = 45

// 快速计算 9 ÷ 2(取整)
int half = 9 >> 1;  // 结果是4

位操作:

c
// 提取第2位(从右往左数,从0开始)
int bit2 = (9 >> 2) & 1;  // (1001 >> 2) = 0010, 0010 & 0001 = 0

// 设置第3位为1
int setBit3 = 9 | (1 << 3);  // 1001 | 1000 = 1001(不变,因为第3位已经是1)

现在你应该对二进制数 1001 的左移和右移操作有了清晰的理解!记住:左移是乘法,右移是除法

posted @ 2025-09-28 17:27  [BORUTO]  阅读(206)  评论(0)    收藏  举报