C语言按位读写二进制

0x00 | 前言

C语言中可以使用union完成二进制的划分,但这种方法最多只能精确到1Byte,而非1bit。在许多场景下,直接对二进制进行位精度的操作效率要远远高于其他算法,本文主要介绍了C语言中简单实现按位读写二进制的方法及其原理。

0x01 | 理论基础

在学习离散数学以及几乎所有的编程语言时,我们都曾接触过真值表。如果我们记或运算为 ∨ \vee ,与运算为 ∧ \wedge ,则易知有如下的真值表。

∨ \vee 10
111
010
∧ \wedge 10
110
000

所以对于单个数10,有如下推论

∵ \because
0 ∨ 1 = 1 0 \vee 1 = 1 01=1
1 ∨ 1 = 1 1 \vee 1 = 1 11=1
0 ∧ 0 = 0 0 \wedge 0 = 0 00=0
1 ∧ 0 = 0 1 \wedge 0 = 0 10=0

∴ \therefore
∀ x ∈ { 0 , 1 } , x ∨ 1 = 1 \forall x \in \{0,1\}, x \vee 1 = 1 x{0,1},x1=1
∀ x ∈ { 0 , 1 } , x ∧ 0 = 0 \forall x \in \{0,1\}, x \wedge 0 = 0 x{0,1},x0=0

我们的代码就从这里写起。

0x02 | 代码实现

注:代码中的bool类型来自标准库头文件stdbool.h,使用bool仅仅是因为1 = true,0 = false

先来看几个二进制数,以及他们的十进制值:

二进制十进制
0000 0000 0000 0000 0000 0000 0000 00000
0000 0000 0000 0000 0000 0000 0000 00011
0000 0000 0000 0000 0000 0000 0000 00102
0000 0000 0000 0000 0000 0000 0000 00113

观察上述二进制,我们可以轻松地将之前的逻辑推论转化为代码:

// 设置n的第i位为f
// i从0数起
void setBinary(int* n,int i,bool f)
{
    if(f)
        *n |= (1l << i);
    else
        *n &= ~(1l << i);
}

至于按位读取,虽然我们确实无法用一串二进制与n直接进行逻辑运算得出结果,但我们可以将视野从一整个二进制串转移到单个的二进制位来。

使用C语言中的按位右移动运算符,我们得以写出这样的代码:

// 返回n的第i位
// i从0数起
bool getBinary(int n,int i)
{
    return (n >> i & 1 == 1);
}

0x03 | 测试

我们使用如下代码进行测试:

#include <stdio.h>
#include <stdbool.h>

void setBinary(int* n,int i,bool f)
{
    if(f)
        *n |= (1l << i);
    else
        *n &= ~(1l << i);
}

bool getBinary(int n,int i)
{
    return (n >> i & 1 == 1);
}

int main(void)
{
    int n = 1;

    printf("%d\n",n);
    // 检查第二位是否是1
    printf("%s\n",getBinary(n,1)?"true":"false");
    // 试图修改第二位为1
    setBinary(&n,1,1);
    printf("%d\n",n);
    // 检查修改后的第二位是否是1
    printf("%s\n",getBinary(n,1)?"true":"false");

    return 0;
}

输出如下:

1
false
3
true

结合上表可知,测试通过。

0x04 | 应用

力扣上有一道直接考这一点的题目:190. 颠倒二进制位 - 力扣(Leetcode)

你可以尝试一下如下代码:

void setBinary(int* n,int i,bool f)
{
    if(f)
        *n |= (1l << i);
    else
        *n &= ~(1l << i);
}

bool getBinary(int n,int i)
{
    return (n >> i & 1 == 1);
}

uint32_t reverseBits(uint32_t n)
{
    uint32_t ret;
    for(int i = 0;i < 32;i++)
        setBinary(&ret,i,getBinary(n,31 - i));

    return ret;
}

zepZE4.png

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 C 语言中,读写二进制文件与读写普通文本文件的过程有一些不同,需要使用二进制模式打开文件,并使用适当的函数进行读写操作。以下是一个简单的示例代码,用于在 C 语言中进行二进制文件读写操作: ```c #include <stdio.h> #include <stdlib.h> struct student { char name[50]; int age; float weight; }; int main() { FILE *fp; struct student stu; // 打开二进制文件 fp = fopen("students.dat", "wb+"); // 写入结构体到文件 strcpy(stu.name, "John"); stu.age = 18; stu.weight = 65.5; fwrite(&stu, sizeof(struct student), 1, fp); // 定位到文件开始 rewind(fp); // 取文件内容 fread(&stu, sizeof(struct student), 1, fp); printf("取文件内容:\n"); printf("姓名:%s\n", stu.name); printf("年龄:%d\n", stu.age); printf("体重:%f\n", stu.weight); // 关闭文件 fclose(fp); return 0; } ``` 这个例子中,程序首先使用 `fopen()` 函数打开一个名为 `students.dat` 的二进制文件,并使用 `wb+` 模式打开,可以进行写入和取操作。然后,程序使用 `fwrite()` 函数将一个 `struct student` 结构体写入文件中。接着,程序使用 `rewind()` 函数将文件指针定位到文件开始,然后使用 `fread()` 函数取文件内容到 `struct student` 结构体变量中。最后,程序使用 `fclose()` 函数关闭文件。需要注意的是,在读写二进制文件时,需要使用 `fwrite()` 和 `fread()` 函数,并且在调用这两个函数时,需要指定要读写的数据类型的大小和数量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值