当前位置: 首页 > news >正文

【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 ^ aa ^ 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(类型)

  1. 正号 (+):用于表示正数,例如 +5 表示正数 5。
  2. 负号 (-):用于表示负数,例如 -5 表示负数 5。
  3. 递增 (++):用于将操作数的值增加 1。可以作为前缀 (++i) 或后缀 (i++) 使用。
  4. 递减 (–):用于将操作数的值减少 1。可以作为前缀 (–i) 或后缀 (i–) 使用。
  5. 取址 (&):用于获取变量的内存地址,例如 &x 表示变量 x 的地址。
  6. 解引用 (*):用于访问指针所指向的内存中的值。例如,*ptr 表示指针 ptr 指向的值。
  7. 逻辑非 (!):用于求取操作数的逻辑非,即取反。例如,!x 表示 x 的逻辑非。
  8. 按位取反 (~):用于对操作数执行按位取反操作。例如, ~ 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)是一种用户自定义的数据类型,用于将不同类型的数据组合成一个单独的实体。结构体能够将多个变量打包成一个整体,方便操作和传递。

结构是⼀些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量,如:标量、数组、指针,甚⾄是其他结构体。

结构体的声明包括两个部分:结构体模板的定义和结构体变量的声明。

  1. 结构体模板的定义:
struct 结构体名称 {数据类型 成员1;数据类型 成员2;// 更多成员...
};

其中,“结构体名称” 是用户定义的结构体类型的名称,可以根据需要自行命名。“成员1”、“成员2” 等是结构体中的成员变量,每个成员变量都有自己的数据类型。

【示例】:坐标结构体的定义

struct Point {int x;int y;
};

这个结构体定义了一个名为 Point 的结构体类型,它有两个成员变量 x 和 y,都是 int 类型。

  1. 结构体变量的声明:
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语言基础】:操作符详解(二)

文章目录 操作符详解一、上期扩展二、单目操作符三、逗号表达式四、下标访问[]、 函数调用()五、结构成员访问操作符六、操作符的属性&#xff1a;优先级、结合性1. 优先级2. 结合性 操作符详解 上期回顾&#xff1a;【C语言基础】&#xff1a;操作符详解(一) 一、上期扩展 …...

模型训练基本结构

project_name/ │ ├── data/ │ ├── raw/ # 存放原始数据 │ ├── processed/ # 存放预处理后的数据 │ └── splits/ # 存放数据集划分&#xff08;训练集、验证集、测试集等&#xff09; │ ├── noteboo…...

Redis 数据结构详解:底层实现与高效使用场景

String&#xff08;字符串&#xff09; 底层实现细节&#xff1a; 动态字符串&#xff08;SDS&#xff09;: SDS相比于C语言的原生字符串&#xff0c;提供了自动内存管理和预分配机制。当字符串长度增加时&#xff0c;SDS会预先分配额外的空间&#xff0c;以减少内存重新分配…...

Vue2:router-link的replace属性

一、情景说明 我们在用浏览器访问网站的时候 知道浏览器会记录访问的历史路径&#xff0c;从而&#xff0c;可以退回到之前的页面 那么&#xff0c;Vue项目中的路由组件&#xff0c;通过router-link跳转&#xff0c;也是可以退回的 这里&#xff0c;我们用replace来屏蔽退回的…...

普中51单片机(DS18B20温度传感器)

DS18B20温度传感器原理 内部结构 64位(激)光刻只读存储器 光刻ROM中的64位序列号是出厂前被光刻好的&#xff0c;它可以看作是该DS18B20的地址序列号。64位光刻ROM的排列是&#xff1a;开始8位&#xff08;28H&#xff09;是产品类型标号&#xff0c;接着的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

这里实际上有三件事&#xff1a;origin master是两件事&#xff0c;origin/master一件事。共计三件事。 两个分支&#xff1a; master 是一个本地分支 origin/master是远程分支&#xff08;它是名为“origin” 的远程分支的本地副本&#xff0c;名为“master”&#xff09; 一个…...

【数据结构】时间复杂度与空间复杂度

目录 时间复杂度 空间复杂度 时间复杂度 算法的时间复杂度并不是指一个代码运行时间的快慢&#xff0c;因为在不同机器上运行的时间肯定不同&#xff0c;因此算法的时间复杂度指的是基本操作的执行次数&#xff0c;他是一个数学意义上的函数。这个函数并不是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 学习网站。在该网站&#xff0c;可以使用 show command 命令展示所有可用命令。你也可以直接访问网站的sandbox&#xff0c;自由发挥。 一、本地篇 基础篇 git commit git commit将暂存区&#xff08;staging area&#xff…...

前端工程化面试题 | 18.精选前端工程化高频面试题

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…...

大公司的工程师是怎么废掉的...

大家好&#xff0c;我是砖一。 此文作者以嵌入式工程师为基本视角&#xff0c;细说了从初阶到高阶工程师的资质需求&#xff0c;并提示工程师职业道路上的陷阱。可供参考。 一&#xff0c;基础知识 一个嵌入式工程师&#xff0c;很多都是从51单片机或者STM32单片机开始&…...

将yolov8权重文件转为onnx格式并在c#中使用

yolo模型转ONNX 在yolov8中&#xff0c;我们将训练结果的.pt权重文件转换为onnx格式只需要使用ultralytics库中的YOLO类&#xff0c;使用pip安装ultralytics库&#xff0c;然后执行下面python代码 from ultralytics import YOLO# 加载YOLOv8模型 model YOLO("best.pt&q…...

在Spring Boot启动时禁止自动配置数据源相关的组件、@SpringBootApplication

一、SpringBootApplication(exclude {DataSourceAutoConfiguration.class})注解 在Spring Boot启动时禁止自动配置数据源相关的组件。 SpringBootApplication(exclude {DataSourceAutoConfiguration.class})注解的使用案例 这个注解通常应该写在微服务项目的主启动类上&…...

程序人生:不积跬步无以致千里

程序人生 癸卯年冬月&#xff0c;往渭南韩城&#xff0c;拜访司马迁祠。入门攀爬而上&#xff0c;至人有困乏之时&#xff0c;抬头现&#xff1a;高山仰止。归路下山&#xff0c;始现三官洞&#xff0c;遥想西汉时三官洞&#xff0c;出口处刻意再拜别&#xff1a;高山仰止。泪…...

通过二叉树例题深入理解递归问题

目录 引入&#xff1a; 例1&#xff1a;二叉树的前序遍历&#xff1a; 例2&#xff1a; N叉树的前序遍历&#xff1a; 例3&#xff1a;二叉树的最大深度&#xff1a; 例4&#xff1a;二叉树的最小深度 例5&#xff1a;N叉树的最大深度&#xff1a; 例6&#xff1a;左叶子…...

【Android 协程常见用法】

我们这里只讲解一下&#xff0c;协程在Android项目中常见用法&#xff0c;原理知识不在进行说明了。 依赖 lifecycleScope只能在Activity、Fragment中使用&#xff0c;会绑定Activity和Fragment的生命周期。依赖库&#xff1a; implementation androidx.lifecycle:lifecycle…...

python 进程笔记一 (概念+示例代码)

1. 进程的概念 进程是资源分配的最小单位&#xff0c;也是线程的容器&#xff0c;线程&#xff08;python 线程 &#xff08;概念示例代码&#xff09;&#xff09;是CPU调度的基本单位&#xff0c;一个进程包括多个线程。 程序&#xff1a;例如xxx.py是一个程序 进程&#xf…...

各中间件数据库默认访问端口总结

说明 在生态丰富的开发环境下&#xff0c;我们常常需要接触很多中间件产品&#xff0c;中间件默认的连接端口以及可视化ui访问端口也时不时的需要用到&#xff0c;这里循序渐进做好登记&#xff0c;以备查阅&#xff01; 中间件/数据库名称默认端口管理台端口默认账号密码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…...

零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?

一、核心优势&#xff1a;专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发&#xff0c;是一款收费低廉但功能全面的Windows NAS工具&#xff0c;主打“无学习成本部署” 。与其他NAS软件相比&#xff0c;其优势在于&#xff1a; 无需硬件改造&#xff1a;将任意W…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

稳定币的深度剖析与展望

一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;加密货币作为一种新兴的金融现象&#xff0c;正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而&#xff0c;加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下&#xff0c;稳定…...

从面试角度回答Android中ContentProvider启动原理

Android中ContentProvider原理的面试角度解析&#xff0c;分为​​已启动​​和​​未启动​​两种场景&#xff1a; 一、ContentProvider已启动的情况 1. ​​核心流程​​ ​​触发条件​​&#xff1a;当其他组件&#xff08;如Activity、Service&#xff09;通过ContentR…...

SQL Server 触发器调用存储过程实现发送 HTTP 请求

文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...

如何配置一个sql server使得其它用户可以通过excel odbc获取数据

要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据&#xff0c;你需要完成以下配置步骤&#xff1a; ✅ 一、在 SQL Server 端配置&#xff08;服务器设置&#xff09; 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到&#xff1a;SQL Server 网络配…...

二维FDTD算法仿真

二维FDTD算法仿真&#xff0c;并带完全匹配层&#xff0c;输入波形为高斯波、平面波 FDTD_二维/FDTD.zip , 6075 FDTD_二维/FDTD_31.m , 1029 FDTD_二维/FDTD_32.m , 2806 FDTD_二维/FDTD_33.m , 3782 FDTD_二维/FDTD_34.m , 4182 FDTD_二维/FDTD_35.m , 4793...

【QT控件】显示类控件

目录 一、Label 二、LCD Number 三、ProgressBar 四、Calendar Widget QT专栏&#xff1a;QT_uyeonashi的博客-CSDN博客 一、Label QLabel 可以用来显示文本和图片. 核心属性如下 代码示例: 显示不同格式的文本 1) 在界面上创建三个 QLabel 尺寸放大一些. objectName 分别…...