C语言invert函数如何实现位取反?

99ANYc3cd6
预计阅读时长 20 分钟
位置: 首页 C语言 正文

invert() 这个函数名并不是 C 语言标准库的一部分,所以没有一个统一的、官方的定义,它通常是一个用户自定义函数,其核心功能是“反转”或“翻转”某个数据。

c语言invert
(图片来源网络,侵删)

最常见的用法是反转一个整数的特定位,这个概念在位操作中非常经典,通常被称为“位反转”或“按位取反”。

下面我将分几种情况来解释 invert() 函数,从最经典到更广泛的用法。


经典用法 - 反转整数的指定位(最常见)

这是 invert() 函数最经典、最常见的实现,它的功能是:将一个整数的某一位(或某几位)的值进行翻转(0变1,1变0),而其他位保持不变。

函数原型

int invert(int num, int bit_pos, int bit_count);
  • num: 要被操作的整数。
  • bit_pos: 开始反转的位的位置(通常从0开始,表示最右边的位)。
  • bit_count: 要反转的位数。

核心思想

这个操作可以通过以下三步完成,这几乎是位操作中“修改特定位”的标准模板:

c语言invert
(图片来源网络,侵删)
  1. 创建掩码:

    • 首先创建一个掩码,这个掩码在需要修改的位上都是 1,其他位是 0
    • 要从第 3 位开始反转 2 位,我们需要一个掩码 ...00011000
    • 创建方法:unsigned int mask = (1 << bit_count) - 1; // 先得到 ...00000111
    • 然后将这个掩码左移到正确的位置:mask = mask << bit_pos; // 得到 ...00011000
  2. 执行反转:

    • 将这个掩码与原数进行异或 操作。
    • 异或 的特性是:0 ^ 1 = 1, 1 ^ 1 = 0, 0 ^ 0 = 0, 1 ^ 0 = 1,这恰好实现了“翻转”的效果。
    • num = num ^ mask;

完整代码示例

#include <stdio.h>
/**
 * @brief 反转整数num中从bit_pos开始的bit_count位
 * @param num 要被操作的整数
 * @param bit_pos 开始反转的位的位置 (从0开始)
 * @param bit_count 要反转的位数
 * @return 反转后的整数
 */
int invert(int num, int bit_pos, int bit_count) {
    // 1. 创建一个掩码,在目标位上为1,其余为0
    //  bit_pos=3, bit_count=2 -> mask = (1 << 2) - 1 = 3 (0b11)
    //       mask = mask << 3 = 24 (0b11000)
    unsigned int mask = (1 << bit_count) - 1;
    mask = mask << bit_pos;
    // 2. 使用异或操作来翻转指定位
    // 异或操作: 0^1=1, 1^1=0, 0^0=0, 1^0=1
    num = num ^ mask;
    return num;
}
int main() {
    int original_num = 0b11010110; // 十进制的 214
    int bit_pos = 2;               // 从第2位开始
    int bit_count = 3;             // 反转3位
    printf("原始数字 (二进制): %08d\n", original_num); // 11010110
    printf("原始数字 (十进制): %d\n", original_num);
    int inverted_num = invert(original_num, bit_pos, bit_count);
    printf("反转后的数字 (二进制): %08d\n", inverted_num); // 11001110
    printf("反转后的数字 (十进制): %d\n", inverted_num);
    // 分析一下:
    // 原始: 1101 0110
    // 掩码: 0001 1100 (从第2位开始,3个1)
    // ------------------- 异或
    // 结果: 1100 1010 (注意:我之前的计算有误,这里重新计算)
    // 让我们重新检查一下:
    // 原始: 1101 0110
    // 掩码: 0000 0111 (bit_count=3) -> 0001 1100 (左移bit_pos=2)
    // 1101 0110
    // ^
    // 0001 1100
    // --------
    // 1100 1010  (结果是 202)
    // 我之前的二进制输出写错了,应该是8位,让我修正一下main函数的打印方式。
    printf("\n--- 更正后的分析 ---\n");
    printf("原始数字 (二进制): %08b\n", original_num);
    printf("原始数字 (十进制): %d\n", original_num);
    inverted_num = invert(original_num, bit_pos, bit_count);
    printf("反转后的数字 (二进制): %08b\n", inverted_num);
    printf("反转后的数字 (十进制): %d\n", inverted_num);
    return 0;
}

运行结果:

--- 更正后的分析 ---
原始数字 (二进制): 11010110
原始数字 (十进制): 214
反转后的数字 (二进制): 11001010
反转后的数字 (十进制): 202

分析:

c语言invert
(图片来源网络,侵删)
  • 原始数: 1101 0110
  • 掩码: 0001 1100 (从第2位开始,3个1)
  • 1101 0110 ^ 0001 1100 = 1100 1010
  • 第2、3、4位 011 被成功翻转为 100,其他位保持不变。

另一种可能的实现 - 按位取反

invert() 也可能被用来实现整个整数的按位取反,这个功能是 C 语言的标准运算符 。

函数原型

int invert_all_bits(int num);

核心思想

直接使用 C 语言的按位取反运算符 ,它会将 num 的每一位都进行翻转(0变1,1变0)。

完整代码示例

#include <stdio.h>
/**
 * @brief 反转整数num的所有位 (按位取反)
 * @param num 要被操作的整数
 * @return 按位取反后的整数
 */
int invert_all_bits(int num) {
    return ~num;
}
int main() {
    int num = 10; // 二进制: 1010
    printf("原始数字: %d (二进制: %04b)\n", num, num);
    int inverted_num = invert_all_bits(num);
    printf("按位取反后: %d (二进制: %04b)\n", inverted_num, inverted_num);
    // 对于有符号整数,要注意符号位
    // 8位有符号数: 00001010 (10)
    // 按位取反后: 11110101 (-11)
    int signed_num = 10;
    printf("\n8位有符号数分析:\n");
    printf("原始数字: %d (二进制: %08b)\n", signed_num, signed_num);
    printf("按位取反后: %d (二进制: %08b)\n", invert_all_bits(signed_num), invert_all_bits(signed_num));
    return 0;
}

运行结果:

原始数字: 10 (二进制: 1010)
按位取反后: -11 (二进制: 1101)
8位有符号数分析:
原始数字: 10 (二进制: 00001010)
按位取反后: -11 (二进制: 11110101)

更广泛的用法 - 反转数组或字符串

invert() 这个名字也可以用于反转一个数组或字符串,虽然 C 语言标准库有 strrev (非标准,某些编译器支持) 和用于反转的算法,但自定义一个 invert_arrayinvert_string 函数也很常见。

函数原型 (反转数组)

void invert_array(int arr[], int size);

核心思想

使用双指针法,一个指针在数组开头,一个在末尾,交换它们指向的元素,然后向中间移动,直到两个指针相遇。

完整代码示例

#include <stdio.h>
/**
 * @brief 反转一个整数数组
 * @param arr 整数数组
 * @param size 数组大小
 */
void invert_array(int arr[], int size) {
    int start = 0;
    int end = size - 1;
    int temp;
    while (start < end) {
        // 交换元素
        temp = arr[start];
        arr[start] = arr[end];
        arr[end] = temp;
        // 移动指针
        start++;
        end--;
    }
}
int main() {
    int numbers[] = {1, 2, 3, 4, 5};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    printf("原始数组: ");
    for (int i = 0; i < size; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n");
    invert_array(numbers, size);
    printf("反转后数组: ");
    for (int i = 0; i < size; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n");
    return 0;
}

运行结果:

原始数组: 1 2 3 4 5 
反转后数组: 5 4 3 2 1 
用法 函数功能 核心技术 适用场景
经典位反转 反转整数的指定位 异或(^) + 掩码 底层编程、硬件控制、加密算法
按位取反 反转整数的所有位 按位取反运算符(~) 数据处理、逻辑运算
数组/字符串反转 反转数组或字符串的元素顺序 双指针交换 数据结构处理、字符串操作

最重要的一点: invert() 不是 C 语言标准库函数,当你看到或使用这个函数时,一定要查看其定义,以确定它具体指的是哪种反转操作,因为它在不同的上下文中有完全不同的含义。

-- 展开阅读全文 --
头像
新云asp转dede如何操作?
« 上一篇 04-12
C语言nextday函数如何实现日期递增?
下一篇 » 04-12

相关文章

取消
微信二维码
支付宝二维码

目录[+]