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

#C语言——学习攻略:操作符的探索(二)

🌟菜鸟主页:@晨非辰的主页

👀学习专栏:《C语言学习》

💪学习阶段:C语言方向初学者

名言欣赏:“计算机科学的核心是解决问题,而不是编程。”


目录

1.  结构成员访问操作符

1.1 结构体(初步)

1.1.1 结构体的声明

1.1.2 结构体变量的定义和初始化

1.2 结构成员访问操作符(直接访问)

2. 操作符的属性:优先级,结合性

2.1 优先级

2.2 结合性

2.3 运算符优先级大汇总

3. 表达式求值

3.1 整型提升

 3.2  算术转换

3.3 问题表达式解析

3.3.1  表达式1

3.3.2  表达式2

3.3.3  表达式3

3.3.4 表达式4

3.3.5  表达式5


1.  结构成员访问操作符

1.1 结构体(初步)

--C语言提供了内置类型:int、char等,但这还不够;假如来描述一更具体的东西,比如书、学生……就要从多方面描述,这时候单一的内置类型行不同。

--在C语言中提供了结构体这种自定义的数据类型,应对多种情况。

结构体是一些值的集合,这些值称为成员变量。结构体的每个成员都可以是不同类型的变量;比如:数组、指针、其他结构题、体等等

1.1.1 结构体的声明

struct tag//struct表明是结构体
{member-list;//一个或多个成员变量
}variable - list;//变量列表
//variable - list; 可有可无,在声明变量类型是可同时定义的变量,且为全局变量

--描述学生

struct Stu
{char name[20];//名字拼音int age;//年龄char id[20];//学号float score;//成绩//……
};//分号绝对不能丢

1.1.2 结构体变量的定义和初始化

--代码块1:结构体变量的定义

struct Stu
{char name[20];//名字拼音int age;//年龄char id[20];//学号float score;//成绩//……
}s1,s2;//全局变量
struct Stu s3;//全部变量int main()
{struct Stu s4;//局部变量return 0;
}

--代码块2:初始化

//一般按顺序初始化
int main()
{struct Stu s4 = {"zhnagsan", "202410102", 85.5f};//局部变量struct Stu s5 = {"cuihua", "2024152331", 96.5f};return 0;
}
//指定顺序初始化
struct Stu s6 = {.age = 20, .name = "wangcai", .score = 67.7f};

--涉及到了 "."运算符。

--代码块:结构体嵌套初始化

//结构体-人声明
struct Peo
{char name[30];int age;char tele[12];
};//结构体-电话本声明
struct Ebook
{struct Peo data[100];//可以存放100个人的消息int count;//当前已存的个数
};int main()
{//结构体嵌套初始化struct Peo p1 = { "zhangsan",20,"15598875462" };struct Ebook eb = { {{"wangwu",19,"13564562077"},{"cuihua",18,"15827602564"}},0 };return 0;
}

1.2 结构成员访问操作符(直接访问)

--直接访问的操作是通过点操作符(.)实现的,接收两个操作数:

int main()
{//结构体嵌套初始化struct Peo p1 = { "zhangsan",20,"15598875462" };struct Ebook eb = { {{"wangwu",19,"13564562077"},{"cuihua",18,"15827602564"}},0 };//直接访问//单个对象printf("%s\n", p1.name);printf("%d\n", p1.age);printf("%s\n", p1.tele);//多个对象printf("%s\n", eb.data[1].name);printf("%d\n", eb.data[1].age);printf("%s\n", eb.data[1].tele);return 0;
}

-- . :结构体成员访问操作符

-- 使用方法: 结构体变量.结构体成员


2. 操作符的属性:优先级,结合性

--操作符有者两个重要的属性:优先级、结合性,这两个属性决定了表达式求值的顺序

2.1 优先级

--优先级指:一个表达式包含多个运算符,哪个先执行,各种操作符i的优先级不同。

3 + 4 * 5;

--在上面的例子,由于乘法运算符优先级高于加法运算符,则先计算4 * 5,再计算加法。

2.2 结合性

--两个运算符的优先级相同,则就需要结合性来判断;根据运算符是左结合、右结合来决定顺序。大部分为左结合(从左到右执行),少部分右结合(赋值运算符=)。

5 * 6 / 2;

--上例中,因为*、/的优先级相同,看结合性都是左结合,那就从左向右执行,先*再/。 

2.3 运算符优先级大汇总

--优先级顺序很多,先记住下面常用运算符的优先级(从高到低),其余随用随查。

  1. 圆括号--(())
  2. 自增/减运算符(++/--)
  3. 乘法(*)、除法(/)
  4. 加法(+)、减法(-)
  5. 关系运算符(<、>……)
  6. 赋值运算符(=)

--注意:圆括号优先级最高,可以用它改变其他运算符优先级。


3. 表达式求值

3.1 整型提升

--C语言中整型算术运算总是至少以缺省 (默认) 整型类型的精度来进行的。为了获取这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升

--整型提升意义:

CPU 的整数运算器(ALU)通常以 int 的长度(如 32 位或 64 位) 作为标准操作数大小。直接处理 char(8 位)、short(16 位)等小类型效率低;

C 语言要求:所有小于 int 的整型(如 charshort)必须先提升为 int 或 unsigned int,再参与运算。

 --实例

char a, b, c;
...
a = b + c;

 --b和c的值被提升为普通整型,然后再执行加法运算。加法运算完成之后,结果将被截断,然后再存储于a中。

--如何进行整型提升?

  • 有符号整数提升是按照变量的数据类型的符号位来提升的
  • 无符号整数提升,高位补0
//负数的整形提升char c1 = -1;
//变量c1的⼆进制位(补码)中只有8个⽐特位:
1111111
因为 char 为有符号的 char
所以整形提升的时候,⾼位补充符号位,即为1
提升之后的结果是:
11111111111111111111111111111111//正数的整形提升char c2 = 1;
变量c2的⼆进制位(补码)中只有8个⽐特位:
00000001
因为 char 为有符号的 char
所以整形提升的时候,⾼位补充符号位,即为0
提升之后的结果是:
00000000000000000000000000000001//⽆符号整形提升,⾼位补0

 

 3.2  算术转换

--若某个操作符的操作数属于不同的类型,除非其中一个操作数转换为另一个操作数类型,不然操作无法执行。下面的层次体系称为寻常算术转换

long double
double
float
unsigned long int
long int
unsigned int
int

--根据顺序可知,操作数的类型在上面这个列表中排名靠后,首先转换为另一个操作数的类型后再执行运算。

3.3 问题表达式解析

3.3.1  表达式1

//表达式的求值部分由操作符的优先级决定。
//表达式1
a*b + c*d + e*f

-- 注意:计算的时候,*比+的优先级高,只能保证*的计算是比+早。但优先级并不决定第三个*比第一个+早执行。(所以写代码时,最好用括号来区分先后)

3.3.2  表达式2

//表达式2
c + --c;

-- c=5

        --如果左操作数的获取在右操作数之前则结果为 5+4=9;
        --如果左操作数的获取在右操作数之后则结果为 4+4=8;

3.3.3  表达式3

//表达式3
int main()
{int i = 10;i = i-- - --i * (i = -3) * i++ + ++i;printf("i = %d\n", i);return 0;
}

--表达式3在不同编译器中测试结果:非法表达式程序的结果

3.3.4 表达式4

#include <stdio.h>
int fun()
{static int count = 1;return ++count;
}
int main()
{int answer;answer = fun() - fun() * fun();printf("%d\n", answer);//输出多少?return 0;
}

 --上面的代码也存在着顺序问题:上述代码 answer=fun() - fun() * fun();中我们只能通过操作符的优先级得知:先算乘法,再算减法。

        --函数的调用先后顺序无法通过操作符的优先级确定。

3.3.5  表达式5

//表达式5
#include <stdio.h>
int main()
{int i = 1;int ret = (++i) + (++i) + (++i);printf("%d\n", ret);printf("%d\n", i);return 0;
}
//尝试在linux 环境gcc编译器,VS2013环境下都执⾏,看结果。

 --当在不同的编译器上运行时,发现在gcc中是 10 4、在vs2中是 12 4。

--因为这个代码中的第一个+在执行的时候,第三个++是不是执行,这个不确定。因为依靠操作符的优先级和结合性是无法决定第一个+和第三个前置++的先后顺序。


结语:本篇文章承接上一篇博客,分享了关于操作符剩余知识,一定要好好理解;如果这篇文章对你的学习有帮助的话,欢迎一起讨论学习,你这么帅给个三连吧~~~

http://www.dtcms.com/a/293500.html

相关文章:

  • 架构师--基于常见组件的微服务场景实战
  • VI Server 操控 LabVIEW 工程
  • DeepSeek Janus Pro本地部署与调用
  • 基于Trae IDE与MCP实现网页自动化测试的最佳实践
  • CI/CD与DevOps集成方法
  • 希尔排序cc
  • 无人机减震模块技术解析
  • Java冒泡排序的不同实现
  • 无人机吊舱减震球模块运行分析
  • 如何在Pico等Android头显中实现无人机低延迟RTMP全景巡检画面播放
  • Cursor(vscode)一些设置
  • 【基于OpenCV的图像处理】图像预处理之图像色彩空间转换以及图像灰度化处理
  • 高亮匹配关键词样式highLightMatchString、replaceHTMLChar
  • 图论的题目整合(Dijkstra)
  • 货车手机远程启动功能的详细使用步骤及注意事项
  • Elasticsearch 字段值过长导致索引报错问题排查与解决经验总结
  • git初始流程
  • [2025CVPR-小目标检测方向]基于特征信息驱动位置高斯分布估计微小目标检测模型
  • 什么是GCN?GCN与GNN有哪些区别?
  • SpringBoot与Vue实战:高效开发秘籍
  • 快手视觉算法面试30问全景精解
  • NumPy核心操作全攻略
  • YOLO12论文阅读:Attention-Centric Real-Time Object Detectors
  • SQLAlchemy 2.0简单使用
  • nodejs模块化
  • 闲庭信步使用图像验证平台加速FPGA的开发:第三十课——车牌识别的FPGA实现(2)实现车牌定位
  • XCKU035‑1SFVA784C Xilinx FPGA KintexUltraScale AMD
  • C# 类 封装 属性 练习题
  • 深度学习 --- 激活函数
  • 计算机底层入门 05 汇编学习环境通用寄存器内存