操作符的深入理解学习并实操

C语言总结八:操作符详细总结 学习C语言中的各种操作符的使用方法及使用场景,可以让我们对于底层编译器的运算逻辑和过程更加清楚,同时能够减少开发中出现的小错误。本篇博客详细总结C语言中的操作符的使用方法、适用场景、及注意事项,学完本篇博客,可以让我们对于各种运算更加清晰,这也是开发人员的基本功。 阅读详情

09 操作符与位运算

1. 一句话总结

位运算是 C 语言最高效的底层操作,本质就是在补码上玩二进制——移位相当于乘除,按位与或非异或各有妙用,整形提升决定了运算结果的正确性。


2. 知识地图

操作符与位运算
├── 进制转换基础
│   ├── 二进制(逢二进一,权重是 2 的次幂)
│   ├── 八进制(0 开头,3 个二进制位 = 1 个八进制位)
│   ├── 十进制(默认写法)
│   └── 十六进制(0x 开头,4 个二进制位 = 1 个十六进制位)
│
├── 整数在内存中的存储
│   ├── 原码:最高位是符号位,其余位表示数值
│   ├── 反码:正数 = 原码,负数 = 符号位不变,其余取反
│   └── 补码:正数 = 原码,负数 = 反码 + 1
│       └── 核心原则:所有计算都在补码上进行
│
├── 整形提升
│   ├── 原因:char/short 等类型在表达式计算时会先提升为 int
│   ├── 有符号类型:高位补符号位
│   └── 无符号类型:高位补 0
│
├── 移位操作符(移动的是补码)
│   ├── << 左移:左边丢弃,右边补 0 → 等效 ×2^n
│   └── >> 右移:右边丢弃,左边补符号位 → 等效 ÷2^n(向下取整)
│
├── 位操作符
│   ├── & 按位与:有 0 就 0,都为 1 才是 1
│   ├── | 按位或:有 1 就 1,都为 0 才是 0
│   ├── ^ 按位异或:相同为 0,不同为 1
│   └── ~ 按位取反:1 变 0,0 变 1
│
├── 位运算经典应用
│   ├── 不借助第三变量交换两个数(异或法)
│   ├── 统计二进制中 1 的个数(n & (n-1) 算法)
│   └── 置位/清零某一位(| 和 & ~)
│
├── 其他操作符
│   ├── 逗号表达式:从左到右依次计算,结果是最后一个
│   ├── [] 下标引用操作符:arr 和 5 是 [] 的两个操作数
│   └── () 函数调用操作符:函数名和参数都是操作数
│
└── 结构体
    ├── 自定义类型,和 int/double 没有本质区别
    ├── . 成员访问操作符
    ├── 支持指定初始化器(C99):{.age=18, .name="wangcai"}
    └── 结构体可以嵌套结构体

3. 核心概念深度解析

3.1 补码:为什么负数存储的不是原码?

CPU 只会做加法,如果直接用原码做减法,电路会非常复杂。补码的设计让"减法"变成"加法":

计算 1 - 1,即 1 + (-1)

用原码算:
  00000000 00000000 00000000 00000001  ←  1
+ 10000000 00000000 00000000 00000001  ← -1
─────────────────────────────────────
  10000000 00000000 00000000 00000010  ← -2 ???错得离谱

用补码算:
  00000000 00000000 00000000 00000001  ←  1 的补码
+ 11111111 11111111 11111111 11111111  ← -1 的补码
─────────────────────────────────────
 100000000 00000000 00000000 00000000  ← 溢出位丢弃,结果 = 0 ✓

负数补码速算口诀:原码符号位不动,其余取反,再加 1。

以 -10 为例(32 位):

原码:  10000000 00000000 00000000 00001010
       ↑符号位
反码:  11111111 11111111 11111111 11110101  ← 符号位不动,其余取反
补码:  11111111 11111111 11111111 11110110  ← 反码 + 1

关键认知:你写的代码里所有整数运算,CPU 都是在补码上做的。printf 用 %d 打印时,再把补码转回原码显示给你看。

3.2 移位操作符:左移是翻倍,右移是折半

<< 左移操作符
════════════════════════════════════════════════════════════
a = 6
补码:  00000000 00000000 00000000 00000110
a << 1:
       00000000 00000000 00000000 00001100  ← 左移一位,右边补 0
结果: 12 = 6 × 2

规则: 左移 n 位,等效于乘以 2^n(前提是不溢出)
     左边丢弃的位如果是 1,结果就不对了——因为溢出了


>> 右移操作符(算术右移)
════════════════════════════════════════════════════════════
a = -10
原码:  10000000 00000000 00000000 00001010
补码:  11111111 11111111 11111111 11110110  ← 负数补码:反码+1
a >> 1:
       11111111 11111111 11111111 11111011  ← 右移一位,左边补符号位(1)
转原码: 10000000 00000000 00000000 00000101  ← 打印结果 = -5
       -10 / 2 = -5 ✓

规则: 右移 n 位,等效于除以 2^n(向下取整)
     左边补的是什么?大部分编译器是算术右移——补符号位

注意:右移时左边补符号位还是补 0,标准说"实现定义"(implementation-defined),但主流编译器(GCC、Clang、MSVC)对有符号数都做算术右移(补符号位)。无符号数右移一定补 0。

3.3 异或交换法:不借助第三变量,三行代码搞定

a = 1, b = 8

Step 1: a = a ^ b
        a = 1 ^ 8 = 9
        b = 8

Step 2: b = a ^ b
        b = 9 ^ 8 = 1
        a = 9

Step 3: a = a ^ b
        a = 9 ^ 1 = 8
        b = 1

最终: a = 8, b = 1  交换完成!

原理拆解(用符号表示):
  设原始值为 A, B
  Step1: a = A ^ B,  b = B
  Step2: b = (A ^ B) ^ B = A ^ (B ^ B) = A ^ 0 = A
  Step3: a = (A ^ B) ^ A = (A ^ A) ^ B = 0 ^ B = B

核心依赖两个性质:
  ① x ^ x = 0(任何数异或自己得 0)
  ② x ^ 0 = x(任何数异或 0 还是自己)
  ③ 异或满足交换律和结合律

⚠️ 踩坑:异或交换法不能用于同一个变量自身交换,即 swap(a, a) 会直接清零。实际工程中,可读性优先,用临时变量更稳妥。


4. 代码实战

4.1 进制表示与打印

#include <stdio.h>

int main()
{
    // 0153 以 0 开头,是八进制
    printf("%d\n", 0153);  // 输出 107(1×64 + 5×8 + 3 = 107)

    // 153 默认十进制
    printf("%d\n", 153);   // 输出 153

    return 0;
}

4.2 移位操作

#include <stdio.h>

int main()
{
    // 左移:正数
    int a = 6;
    int b = (a << 1);
    printf("%d\n", b);  // 12

    a <<= 1;            // 复合赋值:a = a << 1
    printf("%d\n", a);  // 12

    // 左移:负数
    int c = -3;
    // 原码: 10000000 00000000 00000000 00000011
    // 反码: 11111111 11111111 11111111 11111100
    // 补码: 11111111 11111111 11111111 11111101
    // <<1 : 11111111 11111111 11111111 11111010
    // 转原码: 10000000 00000000 00000000 00000110 → -6
    int d = (c << 1);
    printf("%d\n", d);  // -6

    // 右移:负数
    int e = -10;
    // 原码: 10000000 00000000 00000000 00001010
    // 补码: 11111111 11111111 11111111 11110110
    // >>1 : 11111111 11111111 11111111 11111011
    // 转原码: 10000000 00000000 00000000 00000101 → -5
    int f = (e >> 1);
    printf("%d\n", f);  // -5

    return 0;
}

4.3 按位与、或、异或

#include <stdio.h>

int main()
{
    // 按位与 &:有 0 就 0
    int a = 3, b = -5;
    // 3 补码:  00000000 00000000 00000000 00000011
    // -5 补码: 11111111 11111111 11111111 11111011
    // & 结果:  00000000 00000000 00000000 00000011 → 3
    printf("3 & -5 = %d\n", a & b);   // 3

    // 按位或 |:有 1 就 1
    // 3 补码:  00000000 00000000 00000000 00000011
    // -5 补码: 11111111 11111111 11111111 11111011
    // | 结果:  11111111 11111111 11111111 11111011
    // 转原码:  10000000 00000000 00000000 00000101 → -5
    printf("3 | -5 = %d\n", a | b);   // -5

    // 按位异或 ^:相同为 0,不同为 1
    int c = 6, d = -5;
    // 6 补码:  00000000 00000000 00000000 00000110
    // -5 补码: 11111111 11111111 11111111 11111011
    // ^ 结果:  11111111 11111111 11111111 11111101
    // 转原码:  10000000 00000000 00000000 00000011 → -3
    printf("6 ^ -5 = %d\n", c ^ d);   // -3

    return 0;
}

4.4 三种交换变量方法

#include <stdio.h>

// 方法一:临时变量(最推荐,清晰稳妥)
void swap_by_temp()
{
    int a = 1, b = 8;
    int temp = a;
    a = b;
    b = temp;
    printf("临时变量法: a=%d, b=%d\n", a, b);
}

// 方法二:加减法(可能溢出,不推荐)
void swap_by_arithmetic()
{
    int a = 1, b = 8;
    a = a + b;  // a = 9
    b = a - b;  // b = 1
    a = a - b;  // a = 8
    printf("加减法: a=%d, b=%d\n", a, b);
}

// 方法三:异或法(技巧性强,面试常考)
void swap_by_xor()
{
    int a = 1, b = 8;
    a = a ^ b;  // a = 1 ^ 8
    b = a ^ b;  // b = (1 ^ 8) ^ 8 = 1
    a = a ^ b;  // a = (1 ^ 8) ^ 1 = 8
    printf("异或法: a=%d, b=%d\n", a, b);
}

int main()
{
    swap_by_temp();
    swap_by_arithmetic();
    swap_by_xor();
    return 0;
}

4.5 统计二进制中 1 的个数(三种方法)

#include <stdio.h>

// 方法一:模 2 法(仅适用于正数,负数会出错)
// ⚠️ 有 bug,见第 6 节修正
int count_one_v1(int x)
{
    int cnt = 0;
    for (int i = 0; i < 32; i++)
    {
        if ((x % 2) == 1)
            cnt++;
        // 缺少 x /= 2,导致死循环
    }
    return cnt;
}

// 方法二:移位法(正负数都适用,逐位检查)
int count_one_v2(int x)
{
    int cnt = 0;
    for (int i = 0; i < 32; i++)
    {
        if (((x >> i) & 1) == 1)
            cnt++;
    }
    return cnt;
}

// 方法三:n & (n-1) 算法(最优,只循环 1 的个数次)
// 核心原理:n & (n-1) 会消掉最低位的 1
//
// 演示:n = 6 (二进制 0110)
//   n     = 0110
//   n-1   = 0101
//   n&(n-1)= 0100  ← 最低位的 1 被消掉了
//
//   n     = 0100
//   n-1   = 0011
//   n&(n-1)= 0000  ← 又消掉一个 1,结果为 0 结束
//   循环了 2 次 → 有 2 个 1
int count_one_v3(int x)
{
    int cnt = 0;
    while (x)
    {
        x = x & (x - 1);
        cnt++;
    }
    return cnt;
}

int main()
{
    int n = 0;
    scanf("%d", &n);
    printf("二进制中 1 的个数: %d\n", count_one_v3(n));
    return 0;
}

4.6 置位 / 清零指定位

#include <stdio.h>

int main()
{
    int a = 13;  // 二进制: 00001101

    // 将第 5 位(从右往左数,最低位是第 1 位)置为 1
    // 1 << 4 = 00010000
    // a | (1<<4) = 00001101 | 00010000 = 00011101 = 29
    a |= (1 << 4);
    printf("置位后: %d\n", a);  // 29

    // 将第 5 位清零
    // ~(1 << 4) = ~00010000 = 11101111
    // a & ~(1<<4) = 00011101 & 11101111 = 00001101 = 13
    a &= ~(1 << 4);
    printf("清零后: %d\n", a);  // 13

    return 0;
}

4.7 结构体实战

#include <stdio.h>
#include <string.h>

// 结构体是一种自定义类型,和 int、double 没有本质区别
struct stu
{
    char name[10];
    char id[12];
    int age;
};

// 结构体可以嵌套
struct peo
{
    int age;
    char name[12];
    char tele[12];
};

struct ebook
{
    struct peo data[100];  // 存放 100 个人的通讯录
    int count;             // 记录已存放的个数
};

int main()
{
    // 普通初始化
    struct stu s1 = {"zhangsan", "2025440304", 18};

    // C99 指定初始化器:可以按名字赋值,不依赖顺序
    struct stu s2 = {.age = 18, .name = "wangcai", .id = "2025440304"};

    // 嵌套结构体初始化
    struct peo p1 = {18, "wangcai", "2025440304"};
    struct ebook eb = {
        {{18, "yiyi", "1538466919"}, {17, "dada", "556552"}},
        0  // count = 0
    };

    // 访问成员
    printf("%s\n", p1.name);            // wangcai
    printf("%s\n", eb.data[0].name);    // yiyi(注意下标从 0 开始)
    printf("%s\n", eb.data[1].name);    // dada

    return 0;
}

5. 注释提炼

5.1 知识注解类

关于进制转换

二进制转八进制,从右向左三个二进制位可以描述一个八进制位;二进制转十六进制,从右向左四个二进制位可以描述一个十六进制位。

扩展说明:为什么是 3 位和 4 位?因为 2^3 = 8,2^4 = 16。一组二进制位恰好能表示 0~7 或 0~15 的范围。这是计算机底层自然选择的结果,不是巧合。比如二进制 111010,从右往左分组:111 010,八进制就是 72;十六进制分组:0011 1010,就是 3A。

关于整形提升

整形提升和类型有关,如果是 unsigned char 就是无符号位,如果是 signed char,就是有符号位。整形提升都是从高位补符号位或者 0。

扩展说明:C 语言的表达式求值有一个隐式规则——所有比 int 小的整数类型(char、short)在参与运算前,会被自动提升为 int。这么做是因为 CPU 的 ALU(算术逻辑单元)通常按 int 宽度设计,操作 char 反而要额外截断,效率更低。提升时:有符号类型高位补符号位(保持数值不变),无符号类型高位补 0。

关于打印时的符号处理

在打印时看占位符是 %d 还是 %u,如果是无符号,那么最高位就不再是符号位,直接进行计算。

扩展说明:同一块内存,用 %d 解释就是有符号整数,用 %u 解释就是无符号整数。比如 11111111 11111111 11111111 11111111,用 %d 打印是 -1,用 %u 打印是 4294967295。内存里存的都是补码,怎么解释看你的格式控制符。

5.2 个人理解类

我的理解:补码这个设计太精妙了——它让 CPU 不需要区分"加法器"和"减法器",一套电路搞定所有运算。正数的补码等于自己,负数的补码是"取反加一",这样 a + (-b) 就自然等于 a - b。理解了补码,就理解了为什么 ~0 是 -1(全 1 的补码就是 -1),为什么 INT_MIN 是 -2147483648 而 INT_MAX 是 2147483647(负方向多一个,因为 0 占了正数的一个位置)。

我的理解:位运算看起来是"奇技淫巧",实际上它就是硬件最擅长的事。一个 n & (n-1) 消掉最低位 1,比循环 32 次快得多。但写代码时,如果不是性能瓶颈,还是优先保证可读性——你写的 n % 2 别人一眼就懂,n & 1 反而要愣一下。

我的理解:结构体本质上就是你把几个相关变量打包在一起,起个名字。struct stu s1 和 int a 在编译器的视角里,都是"分配一块内存,按某种布局解释"。唯一的区别是 int 的布局是硬件规定的,结构体的布局是程序员定义的。

5.3 踩坑感悟类

⚠️ 踩坑 1:% 取模统计 1 的个数——负数翻车

// 错误写法
int count_one(int x)
{
    int cnt = 0;
    for (int i = 0; i < 32; i++)
    {
        if ((x % 2) == 1)
            cnt++;
        // 忘了 x /= 2!死循环
    }
    return cnt;
}

两个问题:第一,x % 2 对负数会返回 -1 或 0,永远不会等于 1,负数统计一直为 0。第二,即使换成正数,循环里没有 x /= 2,x 永远不变,死循环。用位运算 (x >> i) & 1 或者 n & (n-1) 算法才是正解。

⚠️ 踩坑 2:右移负数时左边补什么?

大部分编译器对 signed 类型做算术右移(补符号位),但 C 标准规定这是"实现定义"行为。写跨平台代码时,如果要对负数做右移,最好用 unsigned 类型,确保补 0,行为可预测。

⚠️ 踩坑 3:异或交换法不能自己和自己交换

int a = 5;
a = a ^ a;  // a = 0
a = a ^ a;  // a = 0
a = a ^ a;  // a = 0  → 数据丢了!

如果你写一个 #define SWAP(a, b) 宏用异或法,调用 SWAP(arr[i], arr[i]) 就会把元素清零。这属于隐蔽 bug,排查起来很痛苦。

5.4 对比总结类

三种交换变量方法对比

方法优点缺点推荐度
临时变量清晰、安全、所有类型通用多用一个变量★★★★★
加减法不借助第三变量可能溢出,仅适用于数值★★☆☆☆
异或法不借助第三变量,不会溢出可读性差,同一变量会清零★★★☆☆

三种统计 1 的个数方法对比

方法时间复杂度适用性推荐度
模 2 法O(32)仅正数(负数有坑)★☆☆☆☆
移位法O(32)正负数都适用★★★★☆
n & (n-1)O(k)(k 为 1 的个数)正负数都适用★★★★★

位操作符速查表

操作符名称规则常见用途
&按位与有 0 就 0清零指定位、判断奇偶
|按位或有 1 就 1置位指定位
^按位异或相同为 0,不同为 1交换变量、加密
~按位取反1 变 0,0 变 1配合 & 清零指定位
<<左移左丢右补 0乘 2 的幂
>>右移右丢左补符号位除 2 的幂

6. 代码修正

Bug 1:统计 1 的个数——模 2 法死循环

修改前:

int count_one(int x)
{
    int cnt = 0;
    for (int i = 0; i < 32; i++)
    {
        if ((x % 2) == 1)
            cnt++;
        // 缺少 x /= 2,i 在变但 x 不变,无限循环判断同一个条件
    }
    return cnt;
}

修改后:

int count_one(int x)
{
    int cnt = 0;
    for (int i = 0; i < 32; i++)
    {
        if ((x & 1) == 1)  // 用 & 1 替代 % 2,正负数都正确
            cnt++;
        x >>= 1;            // 每次右移一位,检查下一个二进制位
    }
    return cnt;
}

原因:x % 2 对负数返回 -1 或 0,永远不等于 1。而且原代码没有改变 x 的值,循环 32 次全在判断同一个最低位。改用 x & 1 检查最低位,然后 x >>= 1 右移推进,才能正确统计所有 32 位。

Bug 2:移位法统计 1 的个数——移位目标错误

修改前:

int count_one(int x)
{
    int cnt = 0;
    for (int i = 0; i < 32; i++)
    {
        if (((x >> 1) & 1) == 1)  // 每次都右移 1 位,永远在检查第 2 位
            cnt++;
    }
    return cnt;
}

修改后:

int count_one(int x)
{
    int cnt = 0;
    for (int i = 0; i < 32; i++)
    {
        if (((x >> i) & 1) == 1)  // 右移 i 位,逐位检查
            cnt++;
    }
    return cnt;
}

原因:x >> 1 永远只右移 1 位,循环 32 次都在检查同一个比特位。应该用 x >> i,每次移动不同的位数,才能逐位检查。


7. 小结

位运算不是炫技,而是理解计算机如何"看见"数字——你写的每一行 a + b,在 CPU 眼里都是补码上的位操作。把原码、反码、补码的转换练熟,把移位和按位逻辑的肌肉记忆建立起来,指针和内存的话题才有地基。


【C语言/C++】操作符详解(一) 文章目录1、引言2、操作符分类2.1算数操作符2.2移位操作符小知识 1、引言 期末将至,四级考试也快来了,最近复习的压力有点大,只能挤出一点点的时间来写博客了。虽然我不是很聪明,相信勤能补拙,希望自己能够将编程学的更好吧。 2、操作符分类 2.1算数操作符 1、算数操作符中的“%”的左右两端必须是整数,求得的是余数。余数的范围是1~被除数。 2、算数操作符中的“/”,求得的是两数相除的商,当“/”除号的两端都是整数的时候,执行的是整数的除法,两段只要有一个是浮点数,执行的就是浮点数除法(即当10/3=3; 阅读详情

相关推荐

深入理解RxJava中的Observable转换操作符

本章深入探讨了RxJava中Observable的转换操作符,包括map、flatMap、concatMap、zip等。通过实例代码和弹珠图,详细解释了这些操作符在数据流转换中的应用和效果。理解这些操作符对处理异步编程和事件流至关重要。

weixin_35835018的博客 412

深入理解C++中的new操作符

今天在学习STL源码时,发现其中关于内存配置器allocate不是很懂,于是在网上找了写资料去了解,发现其还是基于new操作符,不过,必须深入理解new,然后在利用new,进行改造,使之更加高效管理内存。以下是在网上找到的关于new的一些理解: “new”是C++的一个关键字,同时也是操作符。关于new的话题非常多,因为它确实比较复杂,也非常神秘,下面我将把我了解到的与new有关的内容做一个

rave..juine 1226

六自由度机械臂运动学分析及其轨迹规划

六自由度机械臂轨迹规划 通过对比三次多项式插值法与五次多项式插值法的效果,选取后者对机械臂进行轨迹规划,将运动学解导入Matlab Robotics Toolbox仿真,得到各关节角度、速度和加速度与时间关系曲线。 三次多项式插值法 三次多项式有4个待定系数,可同时对起始点和目标点的角度和角速度给出约束条件。 数学公式 MATLAB代码 五次多项式插值法 五次多项式有6个待定系数,可同时对起始点和...

两条眉毛 6万+

【操作符深入理解】

**全网最接地气的C语言关于操作符的介绍,作者实属初学,写博客也是作者学习的一个过程,难免文章中有内容理解不到位或者有不当之处,还请朋友们不吝指正,评论留下各自的见解,相互讨论。希望大家多多给予支持,赠人玫瑰,手有余香!**

qq_43727529的博客 909

WorkBench3.2 + VxWorks6.8安装教程

按照FTP连接主机和目标机,将整个VxWorks6.8的安装分为两个部分,一是在主机(win10系统,可以使用虚拟机或者实体机,推荐使用虚拟机)上安装workbench3.2,进行bootrom与VxWroks映像文件的生成,二是在虚拟机上安装VxWorks系统 19.10.10 首先很高兴文章能帮到大家,但由于本人已不做该方向良久,私信和评论的很多问题现在已经无法解答,如果大家有什么问题欢迎...

Alive的博客 3万+

解决ArcGIS-OpenStreetMap Toolbox-Load OSM File错误

在安装成功OpenStreetMap Toolbox后,首次运行Load OSM File工具,出现以下错误

Zjf的博客 8820

操作符学习

本文摘要: 介绍了C语言中常见的操作符类型及其使用规则。主要包括:1)算术操作符(+、-、*、/、%)和整数/浮点除法的区别;2)移位操作符(左移、右移)及其二进制运算特性,强调不要移动负数位;3)位操作符(&、|、^)的运算规则及应用实例;4)单目操作符、关系操作符和逻辑操作符的使用注意事项;5)条件操作符、逗号表达式以及下标引用、函数调用等特殊操作符。特别讲解了不借助临时变量实现变量交换的两种方法,其中异或交换法更为可靠。还提供了计算整数二进制中1的个数的编程练习。

liu2101772645的博客 963

[比赛]新冠期间饿了么骑士行为预估-数据理解

写在前面 饿了么的比赛的赛题数据理解。 一、骑士行为数据 courier_id 骑士id wave_index 波次index tracking_id 订单id courier_wave_start_lng 波次起始时刻骑士位置 courier_wave_...

Helslie的博客 2943

一文带你吃透操作符,你还不了解操作符吗?(C语言深入解剖篇)

作者介绍:友友们好我是沐曦希,可以叫我小沐💕 作者主页:沐曦希的个人博客主页.🎉 作者的gitee:https://gitee.com/muxi-c-language. 零基础学习C语言系列: 🎈 https://blog.youkuaiyun.com/m0_68931081/category_11742786.html. 🎉小沐和友友们一样喜欢编辑,天天敲代码🤭,沉迷学习,日渐消瘦。很荣幸能向大家分享我的所学,和大家一起进步,成为合格的卷王。✨如果文章有错误,欢迎在评论区✏️指正。那么开始今天的学习吧!😘

m0_68931081的博客 1206

串口通信协议

文章目录前言一、串口通信结构图二、电平三、串口通信协议 前言 本文记录的是平时常用的串口通信有关知识点 提示:以下是本篇文章正文内容,下面案例可供参考 一、串口通信结构图 1、RS232标准串口通讯结构图 2、USB转串口通讯结构图 3、原生的串口到串口 二、电平 串口通信的时候,有三种电平:TTL电平、RS232电平、USB电平 TTL电平是从MCU直接出来的电平 RS323是一种通讯标准,因为高电平+15V低电平–15V电位差30V容错空间大,抗干扰能力强,一般用于工业设备直接通信电平转换芯

weixin_43772611的博客 6850

基于STM32F4XX 、HAL库的GXHT30C温湿度传感器驱动应用C语言程序设计

define GXHT30C_STATUS_WRITE_CHK (1 << 0) // 写数据校验状态。#define GXHT30C_STATUS_HUMI_TRACK (1 << 11) // 湿度跟踪报警。#define GXHT30C_STATUS_TEMP_TRACK (1 << 10) // 温度跟踪报警。#define GXHT30C_STATUS_CMD_STATUS (1 << 1) // 命令执行状态。

PP_Cottage的博客 227

C语言操作符详解

把努力当成一种习惯,而不是三分钟热度。坚持才是王道,每一个你羡慕的收获,都是别人努力用心拼来的。你可以抱怨,也可以无视,但记住,不努力,连输的资格都没有!

weixin_67910574的博客 9114

YOLO26跨时代升级!YOLO26 MLCA注意力机制解读

摘要: 本文提出了一种基于多级上下文聚合(MLCA)注意力机制的改进卷积神经网络。MLCA模块通过局部和全局注意力机制动态调整特征图权重,结合了ECA注意力与自适应池化,显著提升特征表达能力。实验表明,添加MLCA后模型mAP提升12.11,准确率提高5.43。文中详细解析了MLCA1模块的工作原理,包括局部/全局池化、卷积操作和注意力加权机制,并介绍了集成MLCA的Bottleneck_MLCA模块。该机制通过多层次特征融合,在保持计算效率的同时增强模型对关键特征的敏感性。最后提供了YOLOv26-MLC

m0_71589036的博客 283

C语言最全操作符详解,一文精通所有操作符!

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言一、除号“/”二、"%"除法取余数三、左移操作符“<<”和右移操作符“>>”1.左移操作符2.右移操作符四、按位与“&”五、按位或“|”六、按位异或“^”七、赋值操作符“=”和复合赋值操作符1.赋值操作符2.复合赋值操作符八、逻辑非“!”九、&取地址操作符和*解引用操作符十、sizeof操作符十一、按位取反操作符“~”十二、强制类型转换操作符 (类型)十三、双目操作符:逻辑与&&a

m0_57180439的博客 7538

【ComfyUI】Flux + ControlNet 边缘搭配深度、瓷砖、姿态引导图生图

本文介绍了一个基于 Wan 2.1 的 ComfyUI 文生视频工作流,通过 UNet、CLIP 和 VAE 三个核心模型,将文本提示转化为动态视频。工作流包含模型加载、提示词解析、潜空间采样等7个环节,支持分辨率、帧数等参数设置,最终输出高质量视频文件。该方案适用于创意设计、教育培训和多媒体制作等场景,能快速生成符合语义的动态内容。文章还提供了相关开发资源和学习链接,适合AI视频生成领域的研究者和实践者参考。

Mr数据杨 1634

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

C语言 操作符学习

一、操作符分类: 算术操作符 移位操作符 位操作符 赋值操作符 单目操作符 关系操作符 逻辑操作符 条件操作符 逗号表达式 下标引用、函数调用和结构成员 二、算术操作符: + - * / % 除了 % 操作符外,其他的几个操作符可以作用于整数和浮点数。 对于 / 操作符,如果两个操作符都是整数,就执行整数除法。而只要有浮点数,就执行浮点数除法。 ==%==操作符的两个操作符必须为整数。返回的是整除之后的余数。 三、移位操作符 << 左移操作符 >> 右移

sfg0861的博客 749

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

C生万物 | 操作符汇总大全【庖丁解牛,精细讲解】

✒C语言操作符汇总大全,全程精析讲解,拨开云雾见天明☀

做技术人 · 产优质博客 · 找好工作 5911

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

深入理解c语言的操作符 ----【汇总】

c语言

includeevey的博客 1593

C语言操作符

C语言的基础语法巩固之操作符

qq_73270870的博客 2107

【c 语言】算术操作符详解

本博客将详细解析C语言中的各类算术操作符,包括加法、减法、乘法、除法、取模以及增量与减量操作符,通过示例与解释帮助读者深入理解其用法,同时提醒注意事项,避免在实际编程中踩坑。通过掌握这些操作符的使用技巧,您将能够编写出更加高效、准确的C语言代码。

m0_74195174的博客 2311

C语言初阶——操作符详解

C语言操作符,一看就懂!!!

m0_53485626的博客 990

操作符的学习

操作符的学习

m0_66030479的博客 187

【手写 new 操作符实现 - 深入理解 JavaScript 对象创建机制】

JavaScript 手写 new 操作符实现解析 本文深入剖析 JavaScript 中 new 操作符的工作原理,并逐步实现自定义 myNew 方法。核心机制包括:1️⃣ 创建新对象并设置原型链(链接构造函数 prototype)2️⃣ 绑定 this 执行构造函数 3️⃣ 处理返回值(优先返回构造函数返回的对象)。优化版本通过 Object.create 更规范地建立原型链,并完善了类型检查逻辑(支持构造函数返回对象/函数的情况)。通过多个测试用例验证了实现与原生 new 的一致性,包括基本功能、原型

weixin_37342647的博客 1150

【C语言初阶】[万字] 你见过这样用的操作符吗?这里可能有你不知道的操作符知识~ [ C语言操作符详解 一 ]

C语言,万字操作符详解,让你重新认识操作符! 一起来看看吧!

七月.cc的博客 1450

C语言学习入门之操作符详解(下)

本篇继续介绍操作符 6. 单目操作符 6.1 单目操作符介绍 操作符 功能 ! 逻辑反操作 - 负值 + 正值 & 取地址 sizeof 操作数的类型长度(以字节为单位) ~ 对一个数的二进制按位取反 - - 前置,后置- - ++ 前置,后置++ * 间接访问操作符 (类型) 强制类型转换 代码演示: #include<stdio.h> int main() { int a = -10; int* p = NULL; p.

chenchenchencl的博客 864

RxJava2 学习教程(三) 创建操作符和from操作符

上一节我们学习了 RxJava中线程的切换,今天我们将开始学习它强大的操作符,有人会问,操作符是用来干嘛的?在我看来,操作符犹如rxjava的灵魂,它贯穿了被观察者和观察者的整个生命周期,从创建,到进行订阅,到数据传递,到取消订阅等环节。好了,接下来开始我们的学习。 创建操作符 create() 操作符 方法预览: public static <T> Observable&lt...

dolphkon的博客 395
上一篇: 用 Codex CLI 造了一个 Claude Code 桌面客户端
下一篇: 内存函数与数据存储
DDXYcoder
博客等级 码龄1年 140粉丝 29原创
评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值