当前位置: 首页 > 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.lryc.cn/news/596823.html

相关文章:

  • ES6 标签模板:前端框架的灵活利器
  • mongodb的备份和还原(精简)
  • HarmonyOS Flutter Boost完全接入手册:爬完所有坑的实战指南
  • DeepSeek-R1大模型实战:AI编程助手如何提升开发效率
  • JVM、Dalvik、ART区别
  • 用Python实现卷积神经网络(一)
  • 电子电气架构 --- 汽车软件全生命周期
  • Java 堆(优先级队列)
  • 226.翻转二叉树
  • JAVA_EVLEN-面向对象高级二
  • 【C语言进阶】动态内存管理(2)
  • 新手向:Idea的使用技巧
  • 10. isaacsim4.2教程-RTX Lidar 传感器
  • AWS Lambda IoT数据处理异常深度分析:从告警到根因的完整排查之路
  • Vue3 面试题及详细答案120道(61-75 )
  • Python学习:函数的使用
  • webrtc整体架构
  • LeetCode热题100--205
  • Visual Studio中部署PaddleOCRv5 (借助ncnn框架)
  • Flink 状态管理设计详解:StateBackend、State、RocksDB和Namespace
  • 【笔记】Handy Multi-Agent Tutorial 第三章: CAMEL框架简介及实践(实践部分)
  • Redis原理之分布式锁
  • PowerShell自动化核对AD与HR系统账户信息实战指南
  • IDEA202403 超好用设置【持续更新】
  • ZooKeeper在Hadoop中的协同应用:从NameNode选主到分布式锁实现
  • 天津大学陈亚楠教授团队 ACS AEM:焦耳热超快合成非平衡态能源材料——毫秒级制备与跨体系性能突破
  • 昨天去看了电科金仓的发布会,有点东西!
  • 从 Linux 将文件下载到 Windows 的几种实用方法
  • 【AI智能体】Dify 开发与集成MCP服务实战操作详解
  • 嵌入式学习之路