【C语言基础】:操作符详解(二)
文章目录
- 操作符详解
- 一、上期扩展
- 二、单目操作符
- 三、逗号表达式
- 四、下标访问[]、 函数调用()
- 五、结构成员访问操作符
- 六、操作符的属性:优先级、结合性
- 1. 优先级
- 2. 结合性
操作符详解
上期回顾:【C语言基础】:操作符详解(一)
一、上期扩展
【练习一】:不能创建临时变量(第三个变量), 实现两个整数的交换。
方法一:我们可以运用加减法来实现这个功能。
分析:
交换前:a = 3,b = 5;
我们先让 a + b 然后把这个结果赋值给a,也就是a = a + b;
现在a的值变成了8,而b的值还是5;
接下来我们让a - b,把这个表达式赋值给吧,也就是b = a - b;
现在a的值是8,b的值是3;
最后我们只要将a - b这个表达式赋值给a就行啦,也就是a = a - b。
我们就会发现a和b的值发生了互换。
下面是代码实现:
#include<stdio.h>
int main()
{int a = 3;int b = 5;printf("交换前:a = %d b = %d\n", a, b);a = a + b;// a = 8, b = 5b = a - b;// a = 8, b = 3a = a - b;// a = 5, b = 3printf("交换后:a = %d b = %d\n", a, b);return 0;
}

很明显,这种方法也存在着明显的不足,那就是当a和b的值比较大时,a和b可能会超出int的范围,会出现溢出的现象,导致无法进行值的互换。
方法二:按位异或实现
上次我们学习了位操作符,其中按位异或就是对应二进制位相同为0,相异为1。根据这个特性,我们也能实现这个功能。
分析:
首先我们要了解按位异或中几种特殊的情况。比如a ^ a,a ^ 0等等。
1101
1101
按位异或后的结果就是0,而任何数与0按位异或后还是它本身。
根据这个特点,我们也能实现a和b的互换。
注意:按位异或是支持交换律的。
下面说代码实现:
#include<stdio.h>
int main()
{int a = 3;int b = 5;printf("交换前:a = %d b = %d\n", a, b);a = a ^ b;b = a ^ b; // b = a ^ b ^ b, b ^ b就等于0// 现在a = a ^ b, b = aa = a ^ b;// a = a ^ b ^ a, 因为a ^ a等于0// 现在a = b, b = aprintf("交换后:a = %d b = %d\n", a, b);return 0;
}

这种方法也存在着局限性,首先要知道按位操作符的操作数必须是整数,其次代码的可读性也不高,不方便他人理解。
【练习二】编写代码实现:求一个整数存储在内存中的二进制中1的个数。
方法一:通过不断的去模2,除2来获得二进制中1的个数。
注意:这里是指补码。
#include<stdio.h>
int count_one_of_bite(unsigned int n)
{int count = 0; // 计数while (n){if (n % 2 == 1)count++;n = n / 2;}return count;
}
int main()
{int n = 0;scanf("%d", &n);int ret = count_one_of_bite(n);printf("二进制中一的个数:%d\n", ret);return 0;
}

方法二:n & (n - 1)
#include<stdio.h>
int count_one_of_bite(unsigned int n)
{int count = 0; // 计数while (n){count++;n = n & (n - 1);}return count;
}
int main()
{int n = 0;scanf("%d", &n);int ret = count_one_of_bite(n);printf("二进制中一的个数:%d\n", ret);return 0;
}

二、单目操作符
单目操作符(Unary Operator)是一种只操作一个操作数的操作符。
!、++、–、&、、+、-、~*、sizeof(类型)
- 正号 (+):用于表示正数,例如 +5 表示正数 5。
- 负号 (-):用于表示负数,例如 -5 表示负数 5。
- 递增 (++):用于将操作数的值增加 1。可以作为前缀 (++i) 或后缀 (i++) 使用。
- 递减 (–):用于将操作数的值减少 1。可以作为前缀 (–i) 或后缀 (i–) 使用。
- 取址 (&):用于获取变量的内存地址,例如 &x 表示变量 x 的地址。
- 解引用 (*):用于访问指针所指向的内存中的值。例如,*ptr 表示指针 ptr 指向的值。
- 逻辑非 (!):用于求取操作数的逻辑非,即取反。例如,!x 表示 x 的逻辑非。
- 按位取反 (~):用于对操作数执行按位取反操作。例如, ~ x 表示对 x 的每个位取反。
这些是 C 语言中常用的一些单目操作符。它们可以用来执行各种不同的操作,如数值运算、递增递减、逻辑运算和位运算等。
三、逗号表达式
逗号表达式(Comma Expression)是一种由逗号操作符连接起来的表达式,其特点是依次计算每个子表达式,并返回最后一个子表达式的值作为整个表达式的值。逗号表达式的一般形式如下:
expr1, expr2, expr3, ..., exprN
在逗号表达式中,逗号操作符 , 用于连接多个子表达式。在计算逗号表达式时,每个子表达式都会按顺序依次执行,但整个表达式的值将是最后一个子表达式的值。
逗号表达式在 C 语言中可以用于一些特定的场景,如在 for 循环的初始化和迭代部分、函数调用参数中以及变量初始化等地方。例如,在 for 循环中使用逗号表达式可以同时初始化多个变量:
for (int i = 0, j = 10; i < 10; i++, j--) {// 循环体
}
在函数调用参数中使用逗号表达式可以依次计算多个表达式并将它们作为函数的参数:
int result = myFunction(a, b, c+1, d*2);
逗号表达式的使用要谨慎,因为它可能会使代码变得难以理解。在某些情况下,使用逗号表达式可能降低代码的可读性,因此应该根据具体情况慎重考虑是否使用。
【练习】
#include<stdio.h>
int main()
{int a = 1;int b = 2;int c = (a > b, a = b + 10, a, b = a + 1); // 逗号表达式printf("%d\n", c);return 0;
}
可以看到,第六行是一个逗号表达式,从左到右依次进行计算,最后返回最右边的结果。

四、下标访问[]、 函数调用()
[ ] 下标引用操作符
操作数:一个数组名 + 一个索引值(下标)
【举例】
int arr[10];//创建数组
arr[9] = 10;//实用下标引用操作符。
[]的两个操作数是arr和9。
函数调用操作符
接受一个或者多个操作数:第⼀个操作数是函数名,剩余的操作数就是传递给函数的参数。
【举例】
#include <stdio.h>
void test1()
{printf("hehe\n");
}
void test2(const char *str)
{printf("%s\n", str);
}
int main()
{test1(); //这⾥的()就是作为函数调⽤操作符。test2("hello world");//这⾥的()就是函数调⽤操作符。return 0;
}
五、结构成员访问操作符
结构体
结构体(Struct)是一种用户自定义的数据类型,用于将不同类型的数据组合成一个单独的实体。结构体能够将多个变量打包成一个整体,方便操作和传递。
结构是⼀些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量,如:标量、数组、指针,甚⾄是其他结构体。
结构体的声明包括两个部分:结构体模板的定义和结构体变量的声明。
- 结构体模板的定义:
struct 结构体名称 {数据类型 成员1;数据类型 成员2;// 更多成员...
};
其中,“结构体名称” 是用户定义的结构体类型的名称,可以根据需要自行命名。“成员1”、“成员2” 等是结构体中的成员变量,每个成员变量都有自己的数据类型。
【示例】:坐标结构体的定义
struct Point {int x;int y;
};
这个结构体定义了一个名为 Point 的结构体类型,它有两个成员变量 x 和 y,都是 int 类型。
- 结构体变量的声明:
struct 结构体名称 变量名称;
在结构体定义之后,可以通过声明结构体变量来创建实际的结构体对象。
【示例】:使用上述定义的 Point 结构体来声明一个名为 p 的结构体变量
struct Point p;
现在,变量 p 是一个具有两个成员变量的结构体对象。可以通过 . 运算符来访问结构体的成员变量,例如 p.x 或 p.y。
另外,C 语言还提供了一种更简洁的方式来声明结构体变量,即使用 typedef 关键字:
typedef struct {数据类型 成员1;数据类型 成员2;// 更多成员...
} 结构体名称;
这样就可以直接使用 结构体名称 来定义结构体变量,而不需要再写 struct 关键字。例如:
typedef struct {int x;int y;
} Point;
Point p;
这里的 Point 就是一个结构体类型,并且可以直接用于声明结构体变量。
//代码1:变量的定义
struct Point
{int x;int y;
}p1; //声明类型的同时定义变量p1
struct Point p2; //定义结构体变量p2//代码2:初始化。
struct Point p3 = { 10, 20 };struct Stu //类型声明
{char name[15];//名字int age; //年龄
};struct Stu s1 = { "zhangsan", 20 };//初始化
struct Stu s2 = { .age = 20, .name = "lisi" };//指定顺序初始化//代码3
struct Node
{int data;struct Point p;struct Node* next;
}n1 = { 10, {4,5}, NULL }; //结构体嵌套初始化
struct Node n2 = { 20, {5, 6}, NULL };//结构体嵌套初始化
结构体成员的直接访问
结构体成员的直接访问是通过点操作符( .) 访问的。点操作符接受两个操作数。如下所示:
#include <stdio.h>
struct Point
{int x;int y;
}p = { 1,2 };
int main()
{printf("x: %d y: %d\n", p.x, p.y);return 0;
}

使用方式:结构体变量.成员名
结构体成员的间接访问
有时候我们得到的不是⼀个结构体变量,而是得到了⼀个指向结构体的指针。如下所示:
#include <stdio.h>
struct Point
{int x;int y;
};
int main()
{struct Point p = {3, 4};struct Point *ptr = &p;ptr->x = 10;ptr->y = 20;printf("x = %d y = %d\n", ptr->x, ptr->y);return 0;
}

使用方式:结构体指针->成员名
综合举例:
#include <stdio.h>
#include <string.h>
struct Stu
{char name[15];//名字int age; //年龄
};
void print_stu(struct Stu s)
{printf("%s %d\n", s.name, s.age);
}
void set_stu(struct Stu* ps)
{strcpy(ps->name, "李四");ps->age = 28;
}
int main()
{struct Stu s = { "张三", 20 };print_stu(s);set_stu(&s);print_stu(s);return 0;
}

六、操作符的属性:优先级、结合性
C语⾔的操作符有2个重要的属性:优先级、结合性,这两个属性决定了表达式求值的计算顺序。
1. 优先级
优先级指的是,如果⼀个表达式包含多个运算符,哪个运算符应该优先执⾏。各种运算符的优先级是不⼀样的。
3 + 4 * 5;
上⾯⽰例中,表达式 3 + 4 * 5 ⾥⾯既有加法运算符( + ),⼜有乘法运算符( * )。由于乘法的优先级⾼于加法,所以会先计算 4 * 5 ,⽽不是先计算 3 + 4 。


2. 结合性
如果两个运算符优先级相同,优先级没办法确定先计算哪个了,这时候就看结合性了,则根据运算符是左结合,还是右结合,决定执行顺序。⼤部分运算符是左结合(从左到右执行),少数运算符是右结合(从右到左执行),比如赋值运算符( = )。
5 * 6 / 2;
上面示例中, * 和 / 的优先级相同,它们都是左结合运算符,所以从左到右执行,先计算 5 * 6 ,再计算 6 / 2 。
运算符的优先级顺序很多,下⾯是部分运算符的优先级顺序(按照优先级从高到低排列),建议大概记住这些操作符的优先级就行,其他操作符在使用的时候查看下面表格就可以了。
• 圆括号( () )
• ⾃增运算符( ++ ),⾃减运算符( – )
• 单⽬运算符( + 和 - )
• 乘法( * ),除法( / )
• 加法( + ),减法( - )
• 关系运算符( < 、 > 等)
• 赋值运算符( = )
由于圆括号的优先级最高,可以使用它改变其他运算符的优先级。
相关文章:
【C语言基础】:操作符详解(二)
文章目录 操作符详解一、上期扩展二、单目操作符三、逗号表达式四、下标访问[]、 函数调用()五、结构成员访问操作符六、操作符的属性:优先级、结合性1. 优先级2. 结合性 操作符详解 上期回顾:【C语言基础】:操作符详解(一) 一、上期扩展 …...
模型训练基本结构
project_name/ │ ├── data/ │ ├── raw/ # 存放原始数据 │ ├── processed/ # 存放预处理后的数据 │ └── splits/ # 存放数据集划分(训练集、验证集、测试集等) │ ├── noteboo…...
Redis 数据结构详解:底层实现与高效使用场景
String(字符串) 底层实现细节: 动态字符串(SDS): SDS相比于C语言的原生字符串,提供了自动内存管理和预分配机制。当字符串长度增加时,SDS会预先分配额外的空间,以减少内存重新分配…...
Vue2:router-link的replace属性
一、情景说明 我们在用浏览器访问网站的时候 知道浏览器会记录访问的历史路径,从而,可以退回到之前的页面 那么,Vue项目中的路由组件,通过router-link跳转,也是可以退回的 这里,我们用replace来屏蔽退回的…...
普中51单片机(DS18B20温度传感器)
DS18B20温度传感器原理 内部结构 64位(激)光刻只读存储器 光刻ROM中的64位序列号是出厂前被光刻好的,它可以看作是该DS18B20的地址序列号。64位光刻ROM的排列是:开始8位(28H)是产品类型标号,接着的48位是该DS18B20自身…...
2.23C语言学习
P1480 A/B Problem 高精度数除以非高精度数 #include<bits/stdc.h> long long b[66660],c[66660],sum0; char a[66660]; int n; int main(){scanf("%s",a);scanf("%d",&n);int lenstrlen(a);for(int i1;i<len;i){b[i]a[i-1]-0;}for(int i1;…...
origin/master master
这里实际上有三件事:origin master是两件事,origin/master一件事。共计三件事。 两个分支: master 是一个本地分支 origin/master是远程分支(它是名为“origin” 的远程分支的本地副本,名为“master”) 一个…...
【数据结构】时间复杂度与空间复杂度
目录 时间复杂度 空间复杂度 时间复杂度 算法的时间复杂度并不是指一个代码运行时间的快慢,因为在不同机器上运行的时间肯定不同,因此算法的时间复杂度指的是基本操作的执行次数,他是一个数学意义上的函数。这个函数并不是C语言中那种函数&…...
分别使用js与jquery写 单击按钮时出现内容 点击删除按钮不会再向下出现
HTML部分 <body><button id"btn">单击我</button><button id"delAll">删除所有事件</button><div id"test"></div> </bady>jQuery代码 <script type"text/JavaScript" src"…...
【Git】Git命令的学习与总结
本文实践于 Learn Git Branching 这个有趣的 Git 学习网站。在该网站,可以使用 show command 命令展示所有可用命令。你也可以直接访问网站的sandbox,自由发挥。 一、本地篇 基础篇 git commit git commit将暂存区(staging areaÿ…...
前端工程化面试题 | 18.精选前端工程化高频面试题
🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…...
大公司的工程师是怎么废掉的...
大家好,我是砖一。 此文作者以嵌入式工程师为基本视角,细说了从初阶到高阶工程师的资质需求,并提示工程师职业道路上的陷阱。可供参考。 一,基础知识 一个嵌入式工程师,很多都是从51单片机或者STM32单片机开始&…...
将yolov8权重文件转为onnx格式并在c#中使用
yolo模型转ONNX 在yolov8中,我们将训练结果的.pt权重文件转换为onnx格式只需要使用ultralytics库中的YOLO类,使用pip安装ultralytics库,然后执行下面python代码 from ultralytics import YOLO# 加载YOLOv8模型 model YOLO("best.pt&q…...
在Spring Boot启动时禁止自动配置数据源相关的组件、@SpringBootApplication
一、SpringBootApplication(exclude {DataSourceAutoConfiguration.class})注解 在Spring Boot启动时禁止自动配置数据源相关的组件。 SpringBootApplication(exclude {DataSourceAutoConfiguration.class})注解的使用案例 这个注解通常应该写在微服务项目的主启动类上&…...
程序人生:不积跬步无以致千里
程序人生 癸卯年冬月,往渭南韩城,拜访司马迁祠。入门攀爬而上,至人有困乏之时,抬头现:高山仰止。归路下山,始现三官洞,遥想西汉时三官洞,出口处刻意再拜别:高山仰止。泪…...
通过二叉树例题深入理解递归问题
目录 引入: 例1:二叉树的前序遍历: 例2: N叉树的前序遍历: 例3:二叉树的最大深度: 例4:二叉树的最小深度 例5:N叉树的最大深度: 例6:左叶子…...
【Android 协程常见用法】
我们这里只讲解一下,协程在Android项目中常见用法,原理知识不在进行说明了。 依赖 lifecycleScope只能在Activity、Fragment中使用,会绑定Activity和Fragment的生命周期。依赖库: implementation androidx.lifecycle:lifecycle…...
python 进程笔记一 (概念+示例代码)
1. 进程的概念 进程是资源分配的最小单位,也是线程的容器,线程(python 线程 (概念示例代码))是CPU调度的基本单位,一个进程包括多个线程。 程序:例如xxx.py是一个程序 进程…...
各中间件数据库默认访问端口总结
说明 在生态丰富的开发环境下,我们常常需要接触很多中间件产品,中间件默认的连接端口以及可视化ui访问端口也时不时的需要用到,这里循序渐进做好登记,以备查阅! 中间件/数据库名称默认端口管理台端口默认账号密码rabbi…...
鲲鹏arm64架构下安装KubeSphere
鲲鹏arm64架构下安装KubeSphere 官方参考文档: https://kubesphere.io/zh/docs/quick-start/minimal-kubesphere-on-k8s/ 在Kubernetes基础上最小化安装 KubeSphere 前提条件 官方参考文档: https://kubesphere.io/zh/docs/installing-on-kubernetes/introduction/prerequi…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...
