C语言(六) :操作符通关笔记-底层逻辑与实战技巧

EDUCoder实战指南:从Hello World到调试技巧的C语言通关秘籍 本文详细介绍了EDUCoder平台上从Hello World到调试技巧的C语言学习路径,涵盖printf基础、程序顺序性理解、条件判断逻辑及调试技巧等核心内容,帮助新手快速掌握C语言编程基础。 阅读详情

操作符核心知识点梳理

一、核心定位

操作符是编程的 “基础工具”,贯穿变量运算、逻辑判断、代码简化、内存访问的全过程,本次复习重点是理清分类、吃透用法、掌握底层逻辑、规避常踩坑点。

回顾编程知识点时,发现自身对不少操作符的用法仍有混淆,尤其是位操作、移位操作的底层逻辑掌握不扎实,还有操作符优先级、表达式求值经常出错,因此特意梳理这份复习笔记,吃透二进制及位操作相关底层知识,掌握操作符属性及表达式求值规则,为后续编程实战(表达式编写、bug 排查、底层优化)筑牢基础,也方便后续快速回顾。

结合自身复习节奏,全文按基础铺垫→分类梳理→重点突破→底层逻辑→属性与求值→坑点避坑→实战复盘展开,覆盖 11 个核心要点,兼顾基础与难点,以复习视角记录梳理过程和易错点,适合需要系统复习操作符的小伙伴参考。

二、基础铺垫

2.1 二进制和进制转换

  • 核心基础:计算机底层是以二进制(0、1)存储数据的,所有操作符对数据的运算,本质都是对二进制位的操作 —— 这是理解移位、位操作符的前提,需重点牢记。
  • 重点进制转换:主要梳理十进制与二进制(整数 + 小数简要梳理)、二进制与十六进制的转换方法;其中十六进制主要用于简化二进制书写,在后续位操作场景中高频使用,是重点记忆内容。
  • 复习技巧:无需死记复杂推导,重点牢记十进制转二进制除 2 取余、二进制转十进制按位加权求和,结合 1-2 个简单示例辅助记忆,比如将十进制 5 转为二进制,反复练 2 遍即可熟练掌握。

二进制转化成十进制

二进制:1       0       1      1
十进制:1*2^3 + 0*2^2 + 1*2^1 + 1*2^0 = 11

十进制转化为二进制

        

十进制:15 → 除 2 取余得二进制:01111 → 简化为1111(去除高位无意义 0)。

二进制转八进制

二进制每三位对应一位八进制;原因是八进制基数 8 是二进制基数 2 的 3 次方(8=2³),3 位二进制数的取值范围,能完整覆盖 1 位八进制数的所有可能,二者一一对应,转换时直接按位映射即可。示例:二进制101 010 111 → 按三位分组直接转换为八进制。

        

二进制转十六进制

与转八进制逻辑完全相同;核心原因是十六进制基数 16 是二进制基数 2 的 4 次方(16=2⁴)。转换规则:二进制每四位对应一位十六进制,4 位二进制数的所有取值,能完整覆盖 1 位十六进制数的全部可能,二者一一对应,转换时直接按位映射即可。

2.2 原码、反码、补码

  • 核心用途:解决计算机中负数的表示与运算问题,移位、位操作符的运算均基于补码进行,属于底层关键知识点,必须吃透,否则位运算易出错。
  • 三者定义(以整数为例):结合理解整理易懂定义,方便回顾:
    • 原码:符号位(0 正 1 负)+ 数值的二进制绝对值,简单直观但无法直接用于负数运算,这是反码、补码出现的原因。
    • 反码:正数反码 = 原码;负数反码 = 符号位不变,数值位按位取反。
    • 补码:正数补码 = 原码;负数补码 = 反码 + 1(重点);计算机实际存储和运算的是补码,所有整数运算都要基于补码分析。

易错点:负数补码转原码易出错,总结两种通用方法,可交叉验证:

  1. 补码 - 1 得反码,反码按位取反得原码;
  2. 补码直接按位取反 + 1 得原码。

无符号数:无符号位,每一位都是数值位,原码、反码、补码的二进制表示完全相同。

三、操作符整体分类

核心原则:按功能用途分类,每个类别明确「核心作用 + 典型代表 + 使用场景」,拒绝孤立记忆,衔接底层基础知识点,确保知识串联而非零散记忆。

3.1 移位操作符(单独分类,重点突破薄弱点)

  • 核心定义:操作二进制位,将数据的二进制补码位向左 / 向右移动指定位数;仅适用于整数,浮点数使用会报错,运算基于补码进行。
  • 核心代表及用法:结合示例记忆,避免混淆:
    • 左移<<:左边舍弃,右边补 0;等价于整数乘以 2 的 n 次方,效率高于乘法,无符号 / 有符号整数通用该规则。示例代码:
      #include <stdio.h>
      int main()
      {
          int num = 4;
          int n = num << 1; // 仅返回移位结果,不修改num本身
          printf("n = %d\n", n);  // 输出8
          printf("num = %d\n", num); // 输出4,原值不变
          // 若要修改原值,写num = num << 1 或 num <<= 1
          return 0;
      }
      
    • 右移>>:分两种实现,主流编译器默认算术右移:
      1. 算术右移(主流):左边补符号位,右边舍弃;
      2. 逻辑右移:左边补 0,右边舍弃。需注意编译器差异,避免结果异常。

易错点:

  1. 移位位数不能为负数(C 语言标准未定义,不同编译器行为不一致);
  2. 有符号数右移的符号位补位规则需牢记,否则易出现运算结果异常。

建议:自行推导int a=4(二进制 100)左移 1 位、int b=-4右移 1 位的补码运算过程,掌握移位底层逻辑。

3.2 位操作符(&、|、^、~)

注:操作数必须是整数,运算基于补码进行。

  • 核心定义:直接操作数据的二进制补码位,仅适用于整数;常用于底层优化、进制转换、状态判断等场景。
  • 核心代表及用法:
    1. &(按位与):对应位均为 1,结果为 1;否则为 0;常用用途:判断某一位是否为 1、清零指定位。
    2. |(按位或):对应位有一个为 1,结果为 1;否则为 0;常用用途:置 1 指定位。
    3. ^(按位异或):重点复习操作符;对应位不同为 1,相同为 0;核心特性:a^a=0、a^0=a;基于特性可实现交换两个数、翻转指定位。(结尾有重点补充)无临时变量交换两个整数代码:
      #include <stdio.h>
      int main()
      {
          int a = 10;
          int b = 20;
          a = a ^ b;
          b = a ^ b;
          a = a ^ b;
          printf("a = %d b = %d\n", a, b); // 输出a=20 b=10
          return 0;
      }
      
    4. ~(按位非):对应位按位取反(0 变 1,1 变 0);注意:负数补码取反后符号位会变化,运算时需关注符号位。

关键区分:易混淆位操作符(&、|)与逻辑操作符(&&、||),前者操作二进制位,后者操作逻辑值;比如判断两个数是否都为非 0,应使用&&而非&。

3.3 单目操作符

  • 核心定义:只有一个操作数,用于对单个数据进行运算;易和双目操作符混淆,需逐一梳理。
  • 核心代表及用法:
    1. 算术类:++(前置 / 后置自增)、--(前置 / 后置自减)、+(正号,可省略)、-(负号,对补码取反 + 1);前置 / 后置自增自减为重点复习内容,后续单独深度拆解。
    2. 逻辑类:!(逻辑非);规则:将非 0 值转为 0,0 转为 1;示例:!5=0、!0=1。
    3. 取值 / 取地址:&(取地址,获取变量内存地址)、*(取值,通过地址获取变量值);需结合指针基础理解,避免误用。
    4. 强制转换:(类型)(将一个数据强制转为指定类型);注意:浮点数转整数会舍弃小数部分,存在精度丢失问题,需谨慎使用。
    5. sizeof:计算变量 / 类型所占内存大小(单位:字节);易混点:与strlen区分 ——sizeof计算内存大小,strlen计算字符串长度(不包含结束符'\0')。

3.4 逗号表达式(单独分类,明确用法,记录易错点)

  • 核心定义:用逗号,连接多个表达式,从左到右依次执行,整个表达式的结果是最后一个表达式的值。
  • 核心特性:优先级最低,常用于简化代码(如 for 循环的初始化 / 更新部分)。
  • 示例:
    int a=1, b=2;
    int c = (a++, b++, a+b); // 执行顺序:a=2→b=3→c=5,最终结果为5
    
  • 易错点:易误将前面表达式的结果作为最终结果;前面的表达式仅执行,不影响最终结果,最终结果仅由最后一个表达式决定。

3.5 访问类操作符(下标 + 函数调用 + 结构成员,结合实战梳理)

3.5.1 下标访问[]

  • 用于访问数组元素,格式:数组名[下标];核心知识点:本质等价于*(数组名+下标),结合指针基础理解数组访问逻辑。
  • 易错点:下标从 0 开始,编译器不检查下标越界,运行时易出现异常,需注意判断下标范围。

3.5.2 函数调用()

  • 用于调用函数,格式:函数名(参数列表);参数列表可为空(无参函数),但必须保留括号,遗漏会导致编译报错。

3.5.3 结构成员访问操作符(两种形式)

        两种形式易混淆,结合示例记忆,核心用于访问自定义结构体的成员属性;先明确结构体的基础概念:

结构体基础

  • 核心作用:把不同类型的变量打包成一个整体,解决普通变量只能单独存储单一类型数据的问题;比如描述学生(学号 int、姓名 char []、成绩 float),可将多个不同类型属性整合为 “学生类型”,方便管理。
  • 定义原因:实际编程中描述的事物均为多属性,普通变量会让属性相互独立,无法体现 “属于同一事物” 的关联,结构体可解决该问题。
  • 核心定义:关键字struct,分两步:先声明结构体类型(告诉编译器自定义类型的结构),再定义该类型的变量(与int a定义格式一致)。

结构体完整示例代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h> // 字符串赋值需用到strcpy函数

// 声明书本结构体(用于嵌套)
struct Book
{
    // 书本属性
    char bname[20]; // 书名
    float price;    // 价格
}B1; // 声明类型同时定义全局变量B1

// 声明学生结构体(嵌套Book结构体)
struct MyStruct
{
    // 学生属性
    char name[20]; // 名字
    short age;     // 年龄
    char sex[10];  // 性别
    char id[20];   // 学号
    struct Book b; // 支持嵌套结构体
}A1; // 声明类型同时定义全局变量A1

int main()
{
    // 定义局部结构体变量并整体初始化(成员顺序需与声明一致)
    struct MyStruct A2 = { "zhangsan",19,"男","2025345",{"C语言",22.0}};
    printf("学生A2的信息:\n");
    printf("A2学生的书本名称:%s\n", A2.b.bname); // 嵌套结构体成员访问:变量.嵌套结构体.成员

    // 给全局结构体变量A1赋值并读取
    printf("请输入A1学生信息:\n");
    printf("姓名:");
    scanf("%s", A1.name); // 字符数组直接传名,无需&
    printf("年龄:");
    scanf("%hd", &A1.age); // short类型用%hd格式符
    printf("性别:");
    scanf("%s", A1.sex);
    printf("A1的性别:%s\n",A1.sex);
    
    return 0;
}

结构体使用关键注意点:

  1. 字符串成员必须用字符数组(如char name[20]),新手阶段暂不使用char *name(涉及指针);
  2. 字符数组赋值不能直接用=(如A1.name = "张三"是错误的),需用strcpy函数,且必须包含头文件#include <string.h>。

结构体成员访问操作符详解

  1. .(点操作符):用于结构体变量访问成员;格式:结构体变量.成员名;示例:stu.name、A2.b.price。
  2. ->(箭头操作符):用于结构体指针访问成员;格式:结构体指针->成员名;等价于:(*结构体指针).成员名;示例:p->name 等价于 (*p).name(p 为结构体指针)。

3.6 其他常用操作符(补充完善,避免遗漏)

  1. 赋值操作符:=(基础赋值)、+=、-=、*=、/=、%=、&=、|=、^=、<<=、>>=(复合赋值);等价规则:复合赋值 = 运算 + 赋值,如a += b等价于a = a + b,简化代码书写。
  2. 关系操作符:>、<、>=、<=、==(等于判断)、!=(不等于);作用:判断大小 / 相等关系,返回布尔值(0 或非 0),用于条件判断;易混点:==(判断相等)与=(赋值),后续重点梳理。
  3. 逻辑操作符:&&(逻辑与)、||(逻辑或);用于组合条件判断,具有短路求值特性(可简化代码、避免无效运算),后续单独拆解。
  4. 三元运算符:condition ? expr1 : expr2;用于简化简单的 if-else 语句;规则:condition 为真,执行 expr1;为假执行 expr2;示例:求两数最大值max = a > b ? a : b。

四、操作符的核心属性(重点补充:优先级、结合性)

核心意义:优先级和结合性直接决定表达式的运算顺序,是表达式求值经常出错的核心原因;复习重点是牢记高频优先级 + 结合性规则,避免写错表达式。

4.1 优先级

  • 定义:多个操作符共存于一个表达式时,优先级高的先运算;类比数学中的 “先乘除后加减”。
  • 高频优先级梳理(从高到低):
    1. 最高优先级:()(括号,可强制改变运算顺序)、[]、->、.(访问类操作符);技巧:不确定运算顺序时,加括号即可,安全且清晰。
    2. 核心顺序:单目操作符 > 算术操作符 > 关系操作符 > 逻辑操作符 > 赋值操作符 > 逗号表达式(最低)。
  • 易错点:
    1. 单目操作符优先级高于算术操作符(如!a + b,先算!a再算加法);
    2. 赋值操作符优先级低于关系操作符(如a = b == c,先算b==c再将结果赋值给 a)。

4.2 结合性

  • 定义:多个优先级相同的操作符共存时,结合性决定运算方向(从左到右 / 从右到左);与优先级共同决定表达式运算顺序,缺一不可。
  • 高频结合性规则:
    1. 从左到右(左结合):算术、关系、逻辑、逗号、访问类、大部分双目操作符;示例:a + b + c、a > b > c,按从左到右运算。
    2. 从右到左(右结合):单目操作符、赋值操作符、三元运算符;示例:a = b = c(先算b=c再算a=b)、+++a(等价于++(+a))。

实用技巧:不确定运算顺序时,直接加括号(()优先级最高),避免依赖优先级和结合性记忆出错,这是写代码的通用规范。

五、表达式求值

核心:基于操作符的优先级、结合性,结合底层逻辑(补码运算),分析表达式的执行顺序和结果;重点解决 “求值异常” 问题,避免逻辑错误。

5.1求值的三大依据

  1. 操作符优先级;
  2. 操作符结合性;
  3. 操作数的求值顺序;重点:多数操作符未定义操作数求值顺序(如a++ + ++a),不同编译器运算结果不同,需避免写出此类代码。

5.2重点梳理不同类型表达式求值

  1. 含单目操作符的表达式:结合优先级、结合性分析执行顺序;示例:++a + b,先算++a再算加法。
  2. 含位操作、移位操作的表达式:核心步骤 —— 先将操作数转为补码,再按位 / 移位规则运算,最后转回原码得到结果;需结合补码知识分步推导。
  3. 含逗号、赋值操作的表达式:明确逗号表达式 “从左到右执行,结果为最后一个表达式的值”;牢记赋值操作的右结合特性;示例:a = (b++, c++, b+c),先执行逗号表达式,再将结果赋值给 a。

5.3关键易错点

避免写出 “操作数求值顺序未定义” 的表达式(如a = ++a + 1、a++ + ++a),此类代码可移植性差,不同编译器运行结果不同,极易出现 bug。

六、重点操作符深度拆解

原则:聚焦移位、位、单目、访问类等薄弱、易出错的操作符,结合底层基础和操作符属性,搭配 “用法 + 示例 + 易错点”,确保吃透核心逻辑。

6.1 移位操作符 & 位操作符深度拆解

  1. 移位操作符:补充负数移位示例(如int a=-4,a>>1的补码运算过程),分步推导补码移位逻辑,明确算术右移的符号位补位规则,理解原理而非死记结果。
  2. 位操作符:重点拆解^(按位异或),梳理核心应用场景:
    • 交换两个数(无临时变量);
    • 翻转指定位;
  3. 实战延伸:位操作符的底层优化技巧,示例:判断奇数用a & 1(效率高于a % 2 == 1),因位运算是 CPU 直接支持的底层运算,速度更快。

6.2 单目操作符深度拆解(易混淆点突破)

  1. 自增自减(++/--):核心区分 ——前置先运算再使用,后置先使用再运算;示例:int a=2; int b=a++ + ++a;,不同编译器因操作数求值顺序未定义,结果不同,避免依赖固定结果写代码。
  2. sizeof 与 * 的区别:示例:int a[5];,sizeof(a)为数组总大小(5*4=20 字节,int 占 4 字节),sizeof(*a)为首元素大小(4 字节),明确二者计算对象的差异。
  3. 强制转换:演示风险点 —— 精度丢失(int a=3.14;结果为 3)、指针强制转换风险((int*)100;将数值转为指针),提醒自己谨慎使用。

6.3 结构成员访问操作符拆解(贴合实战,解决混淆)

  1. 核心示例:定义学生结构体,分别用结构体变量和结构体指针访问成员,验证等价关系:p->name ≡ (*p).name(p 为结构体指针)。
  2. 核心规则:结构体变量用.,结构体指针用 ->,牢记无混淆。
  3. 易错点:结构体指针访问成员时误用.(如p.name),会直接编译报错,写代码时需反复检查。

七、高频坑点 & 易错点总结

核心:梳理写代码、复习时经常用错、混淆的点,每个坑点搭配 “错误示例 + 正确用法”,结合底层逻辑和操作符属性加深记忆,减少 bug。

坑点 1:混淆位操作符(&、|)与逻辑操作符(&&、||)

  • 错误示例:if(a & b)(本意判断 a、b 均非 0);
  • 正确用法:if(a && b);
  • 核心区别:前者操作二进制位,后者操作逻辑值(0 / 非 0)。

坑点 2:移位操作符的误用

  • 错误行为:移位位数为负数、忽略有符号数右移的符号位补位规则;
  • 后果:不同编译器行为不一致,运算结果异常;
  • 规避:移位位数为非负整数,有符号数右移牢记算术右移规则。

坑点 3:原码、反码、补码混淆

  • 错误行为:用原码直接进行负数运算;
  • 正确用法:所有整数运算(移位、位操作、算术运算)均基于补码进行;
  • 规避:运算前先将操作数转为补码,运算后再转回原码得到结果。

坑点 4:操作符优先级 / 结合性记忆错误

  • 错误示例:a = b + c * d误先算b+c;
  • 解决方案:不确定运算顺序时,直接加括号,安全且清晰。

坑点 5:单目操作符与双目操作符混用

  • 错误示例:++a + b误先算a+b再自增;
  • 规避:牢记单目操作符优先级高于算术等双目操作符。

坑点 6:结构成员访问操作符误用

  • 错误示例:结构体指针用.(p.name)、结构体变量用 ->(stu->name);
  • 核心规则:指针用 ->,变量用.。

坑点 7:逗号表达式结果误用

  • 错误示例:int c = (a++, b++);误将a++结果作为 c 的值;
  • 核心规则:逗号表达式结果为最后一个表达式的值(此例为b++)。

坑点 8:写出操作数求值顺序未定义的表达式

  • 错误示例:a++ + ++a、a = ++a + 1;
  • 后果:不同编译器结果不同,代码可移植性差;
  • 规避:坚决避开此类表达式,拆解为多条语句书写。

八、复习复盘 & 实战小练习

8.1 核心知识点复盘

  1. 底层基础:二进制转换、原码 / 反码 / 补码是移位、位操作符的核心前提,补码运算规则为底层运算基础,需牢记。
  2. 操作符分类:掌握移位、位、单目、访问类、逗号表达式的用法,能区分易混淆类别,快速选择合适的操作符。
  3. 核心属性:优先级、结合性决定表达式运算顺序,记住高频规则,不确定时加括号。
  4. 表达式求值:掌握求值方法,避开未定义求值顺序的陷阱,结合底层逻辑分步分析。

8.2 简单实战练习

  1. 练习 1:进制转换 + 补码运算;将十进制 - 5 转为二进制补码,计算补码左移 1 位、右移 1 位的结果,再转回十进制,检验补码和移位操作的掌握程度。
  2. 练习 2:位操作符应用;用按位异或交换两个整数,用按位与判断一个数是否为奇数,手写代码检验用法,熟悉底层优化技巧。
  3. 练习 3:单目操作符 + 表达式求值;分析int a=3; int b=++a + a-- + sizeof(a);的结果,结合优先级、结合性分步推导。
  4. 练习 4:访问类操作符;定义结构体指针,用.和->两种方式访问其成员并赋值,检验结构成员访问操作符的掌握。
  5. 练习 5:优先级 / 结合性;修正表达式int a=2+3*4>5&&6;的写法,明确运算顺序并计算结果。
  6. 练习 6:坑点排查;手写一段包含位操作符、结构成员访问、表达式求值陷阱的错误代码,找出错误并修正,检验高频坑点的掌握。

九、总结

  1. 延伸思考:操作符不仅是编程的基础工具,其底层逻辑(补码、位运算)更是后续学习指针、内存优化、底层开发的核心;本次复习到位,能大幅提升后续编程效率和代码健壮性,为更难的知识点学习筑牢基础。
  2. 如果在操作符复习中也有混淆的知识点、常踩的坑,欢迎补充交流,分享位操作符、表达式求值的实用技巧,互相巩固复习、查漏补缺、共同进步。

 

补充:按位异或交换两个数的底层逻辑解析

要理解异或交换代码,需先掌握异或运算的3 个核心特性(交换逻辑的基础):

异或运算(^)的核心特性

异或运算规则:两个二进制位相同,结果为 0;两个二进制位不同,结果为 1(简单记:同 0 异 1)。基于规则推导的 3 个关键特性(对任意整数 x、y 都成立):

  1. 自反性:x ^ x = 0(一个数和自己异或,结果一定是 0);
  2. 恒等性:x ^ 0 = x(一个数和 0 异或,结果还是它自己);
  3. 交换律 / 结合律:x ^ y = y ^ x、x ^ y ^ z = x ^ (y ^ z)(异或的运算顺序不影响结果)。

逐行拆解交换逻辑(带变量值推导)

        初始值:a = 10,b = 20;用A表示初始 a (10),B表示初始 b (20),区分 “原始值” 和 “更新后的值”。

  1. 第一步:a = a ^ b执行后:a = A ^ B(10^20),b 仍为原始值 B (20),未被修改;
  2. 第二步:b = a ^ b代入 a 的新值:b = (A^B) ^ B → 结合结合律 + 自反性:A ^ (B^B) = A ^ 0 = A;本质:将原始 a 的值 (10) 赋给了 b,此时 b=10(A),a=10^20(A^B);
  3. 第三步:a = a ^ b代入当前 a 和 b:a = (A^B) ^ A → 结合交换律 + 自反性:B ^ (A^A) = B ^ 0 = B;本质:将原始 b 的值 (20) 赋给了 a,此时 a=20(B),b=10(A),交换完成。

具体数值验证(十进制)

已知:10 ^ 20 = 30、30 ^ 20 = 10、30 ^ 10 = 20;

  1. 第一步:a = 10^20 = 30 → a=30,b=20;
  2. 第二步:b = 30^20 = 10 → a=30,b=10;
  3. 第三步:a = 30^10 = 20 → a=20,b=10。

异或交换的特点

  • 优点

  1. 无临时变量:不需要定义第三个变量(如 temp),节省少量内存空间;
  2. 运算效率高:位运算是 CPU 直接支持的底层运算,比普通临时变量交换法速度更快。
  • 注意点

交换的两个变量必须是不同的内存地址!如果 a 和 b 指向同一块内存(如数组中交换同一个下标元素、a = &b),执行后变量值会变为 0(第一步a=a^b就成了x^x=0,后续步骤均为 0)。

  • 开发建议

实际开发中,临时变量交换法(temp=a;a=b;b=temp)可读性更高,无内存地址限制,是更通用的方式;异或交换法仅适用于追求极致性能的场景。

拓展:位操作符经典笔试应用

  n = n & (n - 1)是二进制位操作的经典技巧,核心作用:消除数字 n 的二进制补码中「最右侧的那个 1」,每执行一次消去一个 1,直到 n 变为 0。

应用 1:统计二进制中 1 的个数

方法一(基础版):

就像求一个十位数的方法一样,通过不断/10的方法,我们不断/2,直到余数为0(有局限,适用于正数)

#include <stdio.h>
int main() {
	int a = 10;
	scanf("%d", &a);
	int sum = 0;
	while (a)
	{
		if (a % 2 == 1)
		{
			sum ++;
		}
		a /= 2;
	}
	printf("Sum: %d\n", sum);
	return 0;
}

输入一个正数5(101,原码等于补码),结果为2是正确的

如果输入-1呢?

原码:1000 0000 0000 0000 0000 0000 0000 0001(最高位 1 是负号,其余是数值位)

反码:1111 1111 1111 1111 1111 1111 1111 1110(符号位不变,数值位取反)

补码:1111 1111 1111 1111 1111 1111 1111 1111(反码 + 1)

代码在逻辑和实际运行显然都是错误的!

方法二(改进局限版)

任何一个数&1得到二进制最低位,然后>>1是计算机中提取二进制每一位的经典方法,核心是通过 &1 取二进制最低位、>>1 右移舍弃最低位,循环执行就能从低位到高位依次拿到一个数的所有二进制位,不管正数还是负数(按补码处理)都适用。

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

//方法二

int main() {

       int a = 0;

       scanf("%d", &a);

       int count = 0;

       for (int i = 0; i < 32; i++)  //考虑负数的情况,循环32次

       {

              if (a & 1)  //if((a & 1) == 1)

              {

                     count++;

              }

              a >>= 1;

       }

       printf("Sum: %d\n", count);

       return 0;

}

那么这样每次就要循环一遍,效率低下!

方法三(效率最高)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
//方法三:n = n & (n-1) 消去最右侧1,循环次数=1的个数
int main() {
    int a = 0;
    scanf("%d", &a);
    int count = 0;
    while (a) {
        a = a & (a - 1);  // 每次消去最低位的1
        count++;          // 消去一次则计数+1
    }
    printf("Sum: %d\n", count);
    return 0;
}

应用 2:判断一个数是否是 2 的次方数

核心原理:2 的次方数的二进制补码中仅有 1 个 1;若 n 是 2 的次方数,则n & (n - 1) == 0(唯一的 1 被消去,结果为 0)。判断条件:if ((n & (n - 1)) == 0) → 成立则为 2 的次方数。

拓展:二进制位置 0 / 置 1 的实现

需求:将 13 的二进制序列的第 5 位修改为 1,再改回 0(位序从 0 开始计数)。

步骤分析

  1. 13 的 32 位二进制(原 / 反 / 补码):0000 0000 ... 0000 1101;
  2. 第 5 位置 1:需构造掩码B=1<<4=16(二进制0000 0000 ... 0001 0000),通过a |= B置 1(按位或可保留原有位,指定位置 1);
  3. 第 5 位改回 0:构造掩码~B(二进制1111 1111 ... 1110 1111),通过a &= ~B置 0(按位与可保留原有位,指定位置 0)。

实现代码

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
    int a = 13;
    printf("原数为%d\n", a); // 输出13
    int b = 1 << 4; // 构造第5位为1的掩码,16
    a |= b; // 第5位置1
    printf("第5位修改为1后为%d\n", a); // 输出29
    a &= (~b); // 第5位改回0
    printf("第5位改回0后为%d\n", a); // 输出13
    return 0;
}

运行结果

本文部分代码:Luminous/Luminousbegin - Gitee.com

我的代码仓库(练习仓库):Luminous/Luminousbegin - Gitee.com

完......

 

C语言入门:从Hello World到理解计算机底层逻辑 编程语言是人与计算机沟通的桥梁,其中C语言作为中级语言,在高级语言的易用性和低级语言的硬件控制能力之间取得了平衡。其核心原理在于通过编译过程将源代码转换为机器指令,直接操作内存和硬件资源,这种特性赋予了它极高的执行效率和底层控制能力。在技术价值上,C语言培养了程序员严谨的计算机思维和内存管理意识,是理解操作系统、编译器、嵌入式系统等核心软件运作机制的基础。从应用场景看,它广泛应用于操作系统开发、嵌入式设备、高性能计算和系统工具等领域。本文以C语言入门为核心,通过分析Hello World程序,深入讲解编译过 阅读详情

相关推荐

一篇博客带你通关操作符(下)

本文介绍了C语言中几种重要的操作符及其使用场景。主要内容包括:1.单目操作符(~、&、*)的二进制取反、取地址和解引用功能;2.关系操作符和逻辑操作符(&&、||)的特性及逻辑短路现象;3.条件操作符(三目运算符)的简洁语法;4.逗号表达式的执行顺序和结果取值规则;5.下标引用、函数调用和结构体成员访问操作符;6.表达式求值中的优先级问题和隐式类型转换(包括算术转换和整形提升)。文章通过代码示例详细说明了各种操作符的使用方法和注意事项,特别强调了逻辑短路和类型转换等容易出错的概念。

jebdhs的博客 1025

【通关分支与循环(一)】---if语句,关系操作符,条件操作符,逻辑操作符

-那么什么时候会用上该语句呢,举个例子,比如我们如果要判断一个数是不是奇数,那么我们用if语句就够了,那要是我们需要判断一个数是奇数还是偶数呢,这个时候就需要if……这个代码的结果会是是都不输出,你们想对了嘛,这就是悬空else问题,else总和最接近的if匹配,从这其实我们可以看出大括号的重要性,如果这里带上大括号,那么是不是就会条理清晰很多呢。但我们会发现有些问题光靠一个if语句无法判断,于是有了else语句和if语句的组合使用,if的嵌套等等,这些知识点都会在接下来讲到的。

会当凌绝顶,一览众山小 1826

计算机二级C语言备考指南:20天冲刺通关秘籍

本文分享二级C语言备考经验,备考分基础复习与刷题冲刺两阶段,核心是刷真题、整理错题。重点突破选择、填空、改错、编程四大题型,考前20天专注复盘错题即可高效提分,助力考生顺利通关

艺杯羹的博客 1315

[C语言]一篇博客带你通关操作符(上)

这篇博客旨在梳理所有的操作符,并介绍其中的重难点。

jebdhs的博客 1197

从PHY芯片看工业网络精准时钟:IEEE 1588v2(PTP)协议实现与选型指南

本文深入解析了工业网络中IEEE 1588v2(PTP)协议的实现与PHY芯片选型要点。通过对比KG7101、RTL8211F等芯片的关键参数,揭示硬件时间戳对纳秒级时钟同步的决定性作用,并提供PTP网络设计中的拓扑布局与配置优化技巧,助力工业自动化场景实现精准时间同步。

weixin_42628688的博客 502

ZedBoard+Vivado(二)——PS + PL实现流水灯

硬件:Zedboard 软件:Vivado2018.2 + Win10 本文参考了http://blog.chinaaet.com/cuter521/p/35978的设计 1 设计 功能:PS + PL流水灯 语言:C 流程:创建工程-&amp;gt;IP Integrator-&amp;gt;综合、实现、生成Bitstream-&amp;gt;SDK 2 流程 2.1 创建工程 跟上一篇步骤完全相同,这里不用添加源文...

q416524389的博客 3695

一文通关C语言中的操作符

操作符从更深程度了解了,内存的空间,对字节,bit位有了更深的体会,我们应该熟练bit位的变化,所带来的影响,这章所需要记忆的东西比较多,不理解还请多阅读几遍,或者留言私信,希望能帮助你们!

YSL070124的博客 247

[FPGA高速以太网]基于Verilog与1G/2.5G Ethernet PCS/PMA IP核的2.5G UDP通信实战

本文详细介绍了基于FPGA与1G/2.5G Ethernet PCS/PMA IP核实现2.5G UDP通信的完整实战方案。文章以黑金AX7A200开发板为硬件平台,深入讲解了从硬件选型、IP核配置、Verilog测试逻辑编写到系统调试与性能验证的全过程,重点剖析了利用SGMII接口与GTP收发器实现高速数据传输的关键技术与避坑指南,为FPGA高速以太网应用开发提供了宝贵经验。

sql99的博客 571

C语言操作符:从“一脸懵”到“玩得溜”,这篇通关指南帮你拿捏

/代码1:变量的定义int x;int y;}p1;//声明类型的同时定义变量p1//定义结构体变量p2//代码2:初始化struct Stu //类型声明//名字int age;//年龄//初始化//指定顺序初始化//代码3int data;//结构体嵌套初始化//结构体嵌套初始化。

2501_91369424的博客 1264

瑞萨 RL78 开发环境实战:从 CS+ for CC 到 e² studio 高效开发

本文详细介绍了瑞萨RL78单片机开发环境的选择与配置,对比分析了CS+ for CC和e² studio的特点及适用场景。内容涵盖环境安装、工程创建、调试技巧、外设驱动开发和低功耗设计等实战经验,为开发者提供全面的RL78入门指南,帮助快速上手并高效开发。

4k5l6j7h8的博客 242

Part03 数据结构

本文介绍了CSP-S初赛中常见的高级数据结构及其实现,包括: 线性结构:双端栈、双端队列、单调队列、优先队列和ST表,重点分析了它们的特点、时间复杂度及典型应用场景。 集合与森林:并查集(带路径压缩和按秩合并)和树的孩子兄弟表示法,展示了多叉树转化为二叉树存储的方法。 特殊树结构:包括二叉堆、树状数组、线段树和字典树,详细说明了它们的构建、查询和更新操作,特别强调了线段树的递归实现和字典树的前缀匹配特性。 每种数据结构都配有核心C++代码实现,涉及数组模拟、动态规划和树形结构等编程技巧,适合算法竞赛选手快速

weixin_43863957的博客 1181

我的C语言好菜,怎么提升自己C语言的水平呢

摘要:本文分享C语言学习经验:1.深入理解指针、内存布局和标准库函数;2.通过算法练习和小项目实践提升编码能力;3.掌握gdb调试技巧精准定位bug;4.探索编译过程和系统调用等底层知识;5.规范代码风格并做好防御性编程;6.善用技术社区资源交流学习。作者以亲身经历说明,C语言需要理论与实践结合,从菜鸟到高手需经历理解底层、大量实践、调试排错等过程,最终获得直接操控计算机的编程能力。

2301_76913576的博客 2123

狂神说docker(最全笔记)

一.Docker入门 1. Docker 为什么会出现 2. Docker的历史 3.Docker最新超详细版教程通俗易懂 Docker是基于Go语言开发的!开源项目 官网 官方文档Docker文档是超详细的 仓库地址 4. 虚拟化技术和容器化技术对比 4.1. 虚拟化技术的缺点 资源占用十分多 冗余步骤多 启动很慢 2.2. 容器化技术 比较Docker和虚拟化技术的不同 传统虚拟机, 虚拟出一条硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软.

qq_21197507的博客 5万+

【C语言】逻辑运算符详解:逻辑与&&与逻辑或||的运用及其短路特性

【C语言】逻辑运算符详解:逻辑与&&与逻辑或||的运用及其短路特性

weixin_57242378的博客 3421

【科学文献计量】标准参考出版年谱(Standard RPYS)和多维参考出版年谱(Multi RPYS)

@[TOC](标准参考出版年谱(Standard RPYS)和多维参考出版年谱(Multi RPYS)) 1 标准参考出版年谱与多维参考出版年谱 1.1 标准参考出版年谱(Standard RPYS) 标准参考出版年谱(Standard Reference Publication Year Spectroscopy)是由Marx, Bornmann, Barth, and Leydesdorff(2014)和Marx and Bornmann(2014)提出的一种量化历史出版物对研究领域影响的方法。该方法通

lys_828的博客 1103

【第1章>第9节】基于FPGA的图像开运算处理算法的Verilog实现

本文介绍了基于FPGA的开运算图像处理实现方法。主要内容包括:1)输入图像二值化处理,通过阈值将灰度图像转换为二值图像;2)数据缓存与窗口提取,使用寄存器数组缓存5行图像数据并构建5×5处理窗口;3)腐蚀运算逻辑,判断窗口内是否全为白色像素;4)膨胀运算逻辑,检测窗口内是否存在白色像素。最后给出了Verilog实现方案,通过级联腐蚀和膨胀模块完成开运算处理。该方法可用于FPGA图像处理算法开发。

MATLAB,verilog,python,opencv,tensorflow,caffe,C,C++ 315

C语言7天通关计划:浙大翁恺+哈佛CS50精华笔记整理

C语言作为一门经典且强大的编程语言,在系统编程、嵌入式开发、游戏开发等众多领域都有着广泛的应用。浙大翁恺老师的C语言课程深入浅出,哈佛CS50课程则以其趣味性和实用性闻名。结合这两门课程的精华,为大家制定一个C语言7天通关计划,让你在一周内快速掌握C语言的核心知识。

星辰夜语的博客 565

深度学习工具包 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 语言第 13 天学习笔记:指针的通关秘籍(指针变量与变量指针)

本文为C语言指针基础笔记,涵盖**指针概念**(即内存地址,含变量指针与指针变量)、内存基础知识(按字节划分,多字节数据以首字节为基地址)、指针操作(用&取变量地址,借指针变量间接访问数据)、指针变量定义(语法“数据类型 *变量名”,需与指向对象类型一致),并提及指针是C语言重要特性,为动态内存管理和数据结构实现提供支持。

m0_75239201的博客 1383

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

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

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

算法实战笔记:栈与队列的底层逻辑与高阶应用(六)

本文深入解析栈与队列的底层实现与高阶应用。首先介绍Java中更推荐使用Deque接口实现栈和队列,并分析ArrayDeque的性能优势。接着探讨栈的四大经典场景:操作系统目录切换、括号匹配、字符串去重和逆波兰表达式。重点剖析单调队列在滑动窗口最大值问题中的动态淘汰机制,以及优先级队列(堆)在Top-K问题中的精妙应用。通过底层原理到高阶算法的系统讲解,展现栈与队列从简单数据结构到解决复杂问题的强大演化能力。

曦煜墨白的博客 495

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

C语言【基础篇】之初识C语言—开启编程之旅

在我看来,学习一门编程语言之前,我们应该先弄清楚这门语言的由来、发展以及前景,我们才能抱以更大的热情进入学习中。本文作为C语言的引入,讲述了编程语言的发展、什么是C语言以及将C语言作为首选语言的好处,接下来的篇章,我将会讲解C语言的基础语法,希望能帮助到您。

2402_88461821的博客 1438

C++面试通关秘籍:从底层原理到实战技巧深度解析

C++作为一门高性能系统编程语言,其核心在于对内存、对象模型和运行时效率的精细控制。理解其底层原理,如虚函数表(vtable)实现多态、智能指针(如shared_ptr, unique_ptr)基于RAII管理资源生命周期,是编写高效、安全代码的基础。这些机制直接决定了程序的性能与稳定性,在现代后端开发、游戏引擎、基础设施软件等场景中至关重要。本文聚焦C++面试高频考点,通过剖析STL容器(如vector的倍增扩容)、现代C++特性(移动语义、Lambda表达式)及经典陷阱(迭代器失效、循环引用),旨在帮助

cqbh2011的博客 429

零基础通关C语言——chapter 4——分支和循环上

我们在chapter2中提到过语句的分类,知道在五种语句当中 控制语句 的重要性,而控制语句又可以分为三类语句,即分支语句,循环语句和转向语句它们的关系可以看一下下面的思维导图今天我们就来先讲讲其中的分支与循环语句的一部分ok,明确了本篇博客的目标,我们就开始吧!一.if语句经过前面知识的学习,我们已经知道了要实现分支我们可以使用if 和 switch 语句首先来看一下if语句吧!

2301_79345909的博客 239

零基础通关C语言——chapter3——C语言数据类型和变量下

开头声明(超小声) 个人觉得,进入本篇,难度比前两篇又更上一个台阶。所以在讲解之外,会附上一些题目当作巩固训练。废话不多说,直接开始我们今天的内容! 主要的操作符有以下几类算术操作符赋值操作符单目操作符关系操作符逻辑操作符条件操作符移位操作符位操作符 作为初步学习的我们,今天先学习前三者即算术操作符,赋值操作符和单目操作符 a. + 和 -额,这个就不用解释了。。。b. * 注意,在计算机中打不出我们在数学中写的乘号,所以用*表示c. /在C语言中 ,整数除法是整除,只会返回整数部分,会

2301_79345909的博客 291

20天通关计划:GitHub万星C语言学习路线

C语言作为一门经典且强大的编程语言,在系统开发、嵌入式编程、游戏开发等众多领域都有着广泛的应用。GitHub上有许多备受关注(万星级别)的C语言学习资源,为我们提供了丰富的学习素材。本文将基于这些优质资源,为你制定一个20天的C语言通关学习计划,助你快速掌握C语言的核心知识。

星辰夜语的博客 658

解锁C语言指针:从入门到进阶的通关秘籍

指针作为 C 语言中最具特色和挑战性的部分,其重要性不言而喻。它是连接高级语言抽象与底层硬件操作的桥梁,为我们提供了直接操作内存的能力。通过深入学习指针,我们不仅掌握了一种强大的编程工具,更理解了计算机内存管理的底层机制,这对于提升编程能力和解决复杂问题的能力具有重要意义。​在学习指针的过程中,我们从最基础的指针概念入手,逐步深入到指针变量的定义、操作符的运用、不同类型指针的特点以及指针在数组和函数中的应用。每一个知识点都像是拼图的一块,共同构成了指针知识的完整画面。

2301_80137336的博客 970

C语言逻辑通关:搞定switch与三大循环,学会用break掌控程序节奏

本文系统性地介绍了 C 语言中控制程序流程的核心语法结构,主要包括分支结构和循环结构两大类。分支结构方面,重点讲解了switch语句。它是一种多分支选择结构,相比多重if...else更具可读性。switch后的表达式必须是整型(包括字符类型)。case标签后必须是整型常量表达式,且与case关键字间需有空格。每个case分支通常以break语句结束,以防止“贯穿”执行。但多个case可共享同一段代码块,此时break的位置需根据逻辑需求灵活放置。default子句用于处理未匹配任何case。

2502_91282167的博客 490
上一篇: C语言(五):吃透递归的底层逻辑—我的回头重学实战总结
下一篇: C语言(七): 指针(上)-内存地址到数组指针的核心逻辑
DreamLuminous
博客等级 码龄1年 55粉丝 76原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值