初识结构体,整型提升及操作符的属性

目录

  • 一、结构体成员访问操作符
  • 1.1 结构体
  • 二、操作符的属性:优先级、结合性
    • 2.1 优先级
    • 2.2 结合性
      • C 运算符优先级
  • 三、表达式求值
    • 3.1 整型提升
    • 3.2 算数转化
  • 总结


一、结构体成员访问操作符

1.1 结构体

C语言已经提供了内置类型,如:char,short,int,long,float,double等,但是只有这些内置类型还是不够的,假设我想描述学生,描述一本书,这时单一的内置类型是不行的。

描述一个学生需要名字,年龄,学号,身高,体重等

描述一本书需要作者,出版社,定价等。C语言为了解决这个问题,增加了结构体这种自定义的数据类型,让程序员可以自己创造适合的类型。

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

这里可以和数组相比较

数组:是一组相同类型的元素的集合

struct tag
{member-list;
}variable-list;//变量列表

这里的member-list可能有多个值,值叫成员变量。variable-list变量列表可有可无。

//声明了一个结构体类型
struct Stu
{//1个或多个成员 - 这些成员都是用来描述学生的char name[20];int age;char id[11];float score;//...
} s6,s7,s8;//全局变量

其大体形式就如图示代码,s6,s7,s8就是变量列表,其相当于在声明类型的时候顺便创建了几个变量,相当于全局变量,也可以不写,在下面单独创建。

//声明了一个结构体类型
struct Stu
{//1个或多个成员 - 这些成员都是用来描述学生的char name[20];int age;char id[11];float score;//...
} s6,s7,s8;//全局变量,声明类型的同时定义s6,s7,s8struct Stu s4;//全局变量,定义结构体变量s4
struct Stu s5;//全局变量int main()
{int num = 0;struct Stu s1 = {"zhangsan", 20, "2024010102", 85.5f};struct Stu s2 = {.age=18, .name="wangcai",.score=95.5f,.id = "2025010102"};//指定顺序初始化struct Stu s3;//局部变量return 0;
}

在这里插入图片描述
编译器在默认情况下会将85.5认定为double类型,所以要加一个f,搞成float类型。

而且在默认情况下,结构体的初始化变量只能按顺序初始化,即按结构体的声明顺序来创建,如果想要指定初始化顺序,就要使用操作符(.)来访问结构体成员了。
使用方法:结构体变量.成员名

结构体也可以嵌套使用,即在结构体中引用结构体:

//声明了一个结构体类型
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, "15598888888"};struct Ebook eb = { {{"wangwu", 19, "13396668866"},{"cuihua", 18, "18696866688"}},  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;
}

这里也不太好说,直接看监视窗格就懂了:
在这里插入图片描述
在这里插入图片描述


二、操作符的属性:优先级、结合性

C语言的操作符有两个重要的属性:优先级、结合性,这两个属性决定了表达式求值的计算顺序。

2.1 优先级

优先级指的是,如果一个表达式包含多个运算符,哪个运算符应该优先执行。各种运算符的优先级是不一样的。

3 + 4 *5

该示例中,表达式3+45里既有加法运算符,又有乘法运算符。由于乘法的优先级高于加法,所以会先计算45,而不是先计算3+4.

2.2 结合性

如果两个运算符优先级相同,优先级没办法确定先计算哪个了,这时候就需要看结合性了,则根据运算符是左结合,还是右结合,决定执行顺序。大部分运算符是左结合(从左到右执行),少数运算符是右结合(从右向左执行),比如赋值运算符(=)

5 * 6 / 2

该示例中,*和/的优先级相同,他们都是左结合运算符,所以从左到右执行,先计算5×6,再计算/2。

运算符的优先顺序很多,下面是部分运算符的优先级顺序(按照优先级从高到低排列)

  • 圆括号(())
  • 自增运算符(++),自减运算符(–)
  • 单目运算符(+和-)
  • 乘法(*),除法(/)
  • 加法(+),减法(-)
  • 关系运算符(<、>等)
  • 赋值运算符(=)

补充:圆括号的优先级是最高的,可以使用它来改变其他运算符的优先级。

C 运算符优先级

优先级运算符描述结合性
1++ –
()
[]
.
->
(type){list}
后缀/后置自增和自减
函数调用
数组下标
结构体和共用体成员访问
通过指针访问结构体和共用体成员
复合字面量[C99]
从左到右
2++ –
+ -
! ~
(type)
*
&
sizeof
_Alignof
前缀自增和自减[注释1]
单目正负
逻辑非和按位取反
强制类型转换
间接访问(解引用)
取地址
求大小[注释2]
对齐要求[C11]
从右到左
3* / %乘法、除法和取余从左到右
4+ -加法和减法从左到右
5<< >>按位左移和右移从左到右
6< <=用于关系运算符 < 和 ≤ (分别对应)-
7> >=用于关系运算符 > 和 ≥ (分别对应)-
8== !=用于关系运算符 ==(等于)和 !=(不等于) (分别对应)-
9&按位与-
10^按位异或(独占或)-
11|按位或(包含或)-
12&&逻辑与-
13||逻辑或-
14?:条件运算符[注释3]从右到左
15[注释4]=
+= -=
*= /= %=
<<= >>=
&= ^= |=
简单赋值
加法赋值、减法赋值
乘法赋值、除法赋值、取余赋值
按位左移赋值、按位右移赋值
按位与赋值、按位异或赋值、按位或赋值
-
16,逗号从左到右

三、表达式求值

3.1 整型提升

C语言中整型算术运算总是至少以默认整型类型的精度来进行的。

为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升

整型提升的意义
表达式中的整型运算要在CPU的响应运算器件内执行,CPU整型运算器(ALU)的操作数的字节长度一般就是int的字节长度,同时也是CPU的通用寄存器的长度。
因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。
通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然极其指令中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转换为int或unsigned int,然后才能送入CPU去执行运算。

如何进行整型提升呢?

  1. 有符号整数提升是按照变量的数据类型的符号位来提升的
  2. 无符号整数提升,高位补0

多说无益,拿例子来看:
在这里插入图片描述
看到这串代码,你的第一反应c的值是多少呢?
会不会是140呢?
哈哈我既然拿出来了,它当然就没有那么简单了,打印出的值是-116

首先排除140,因为char类型的取值范围是:-128-127,他根本就存不下140,这里就要进行整型提升的操作:

首先这里20是int类型,4个字节要放到char里面去,char只有一个字节的空间,所以只能有8个比特位,这就需要截断一部分了,这里是截断高位,保留低位,这里a和b相加的时候要发生整型提升
在这里插入图片描述
在我们当前的msvc编译器下,char就是所谓的signed char,所以整型提升就按第一个走

过程展示

在这里插入图片描述

因为这里%d注释处的原因,加和起来的c也需要整型提升

3.2 算数转化

如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数转换为另一个操作数的类型,否则操作无法进行,下面的图中的层次体系就称为寻常算术转换
在这里插入图片描述
编译器会根据内容自动转换数据类型,是由小的类型向大的类型转化,就如箭头所指方向
在这里插入图片描述
比如这里整型100+浮点型55.5,编译器就会自动将整型100转换为浮点型100,再进行相加和。


总结

虽然在这里已经有了操作符的优先级和结合性,但如果我们写代码的时候表达式过于复杂,计算结果的路径不唯一,一串代码同一函数多次调用,任有可能写出问题代码(因为调用的先后次序无从得知,不同编译器下的计算次序可能不同),所以在平时写代码的时候,表达式还是建议多次拆分,简单化更好。

这次决定把文章的重点内容设为标题看一看效果,因为前几篇文章流量不太好,有点小伤心,希望喜欢作者文章的靓仔靓女多多点赞支持一下,你们的支持就是我最大的动力!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/bicheng/83938.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JVM-内存结构

&#x1f9e9; 一、JVM内存五大核心结构详解 &#x1f4cc; 1. 程序计数器&#xff08;Program Counter Register&#xff09; 特性说明作用记录当前线程执行的字节码行号指示器&#xff08;分支/循环/异常处理的核心&#xff09;线程私有✅ 每个线程独立存储指令位置异常❌ …

从 Revit 到 3DTiles:GISBox RVT 切片器如何让建筑图元在 Web 端展示

在GIS&#xff08;地理信息系统&#xff09;行业蓬勃发展的当下&#xff0c;数据处理与展示的效率和精准度成为关键。GISBox作为一款功能强大的一站式三维GIS数据编辑、转换、发布平台&#xff0c;凭借其独特的“RVT切片器”功能&#xff0c;在RVT图元处理方面也有着不俗的表现…

【Linux】为 Git 设置 Commit 提交模板方法,可统一个人或者项目的提交风格

为 Git 设置 Commit 提交模板 新建模板文件。注意之后不能删除该文件。 gedit ~/.gitmessage.txt粘贴自己的模板。可以给 AI 提自己的需求&#xff0c;定制一个模板&#xff0c;例如 # <type>(<scope>): <description> # # [optional body] # # [optional…

Android第十二次面试GetX库渲染机制

核心引擎&#xff1a;GetX / Obx 的魔法 .obs 是数据响应式化的关键操作&#xff0c;它将普通变量转换为可观察(Observable)对象&#xff1a; // 传统变量 - 无法自动通知更新 int count 0; // 响应式变量 - 自动通知能力 var count 0.obs; // RxInt(0) Obx 是 UI ​响应式…

用 Whisper 打破沉默:AI 语音技术如何重塑无障碍沟通方式?

网罗开发 &#xff08;小红书、快手、视频号同名&#xff09; 大家好&#xff0c;我是 展菲&#xff0c;目前在上市企业从事人工智能项目研发管理工作&#xff0c;平时热衷于分享各种编程领域的软硬技能知识以及前沿技术&#xff0c;包括iOS、前端、Harmony OS、Java、Python等…

ubuntu 添加应用到启动菜单

使用Alacarte菜单编辑器 Alacarte是一个简单易用的菜单编辑器&#xff0c;可以帮助用户添加、删除或编辑应用程序的启动菜单项。 安装Alacarte sudo apt-get install alacarte 执行alacarte alacarte 使用说明 选择新建项目进行添加 "Name"栏填自定义的名称&quo…

【学习笔记】构造函数+重载相关

【学习笔记】构造函数重载相关 一、构造函数 构造函数在创建对象的过程就会执行&#xff0c;带参数与不带参数&#xff0c;带参数的构造函数会默认将成员变量赋值传进去的参数。 class Layer { private:int layer_id; // 层IDstd::string layer_json; // 层的JSON配置…

6.6 计算机网络面试题

描述一下打开百度首页后发生的网络过程 网页非常慢转圈圈的时候&#xff0c;要定位问题需要从哪些角度&#xff1f; server a和server b&#xff0c;如何判断两个服务器正常连接&#xff1f;出错怎么办&#xff1f; 服务端正常启动了&#xff0c;但是客户端请求不到有哪些原因?…

Java -jar命令运行外部依赖JAR包的深度场景分析与实践指南

Java -jar命令运行外部依赖JAR包的深度场景分析与实践指南 引言&#xff1a;外部依赖JAR的必要性 在Java应用部署中&#xff0c;java -jar命令是启动可执行JAR包的标准方式。但当应用需要依赖外部JAR文件时&#xff08;如插件系统、模块化部署、共享库等场景&#xff09;&…

XHR / Fetch / Axios 请求的取消请求与请求重试

XHR / Fetch / Axios 请求的取消请求与请求重试是前端性能优化与稳定性处理的重点&#xff0c;也是面试高频内容。下面是这三种方式的详解封装方案&#xff08;可直接复用&#xff09;。 ✅ 一、Axios 取消请求与请求重试封装 1. 安装依赖&#xff08;可选&#xff0c;用于扩展…

2025最新Java日志框架深度解析:Log4j 2 vs Logback性能实测+企业级实战案例

一、为什么printStackTrace是"代码坟场"&#xff1f; 你写的日志可能正在拖垮系统&#xff01; 在Java开发中&#xff0c;直接调用printStackTrace()打印异常堆栈是最常见的"自杀式操作"。这种方式会导致三大致命问题&#xff1a; 无法分级控制&#xff…

前端面试四之Fetch API同步和异步

Fetch API&#xff08;Fetch Application Programming Interface&#xff09;是一个现代的、基于Promise的网络请求接口&#xff0c;用于在浏览器环境中发起网络请求并处理响应。它是对传统XMLHttpRequest的改进&#xff0c;提供了更简洁、灵活和强大的功能&#xff0c;广泛应用…

ubuntu 20.04挂载固态硬盘

我们有个工控机&#xff0c;其操作系统是ubuntu 20.04。可以接入一个固态硬盘。将固态硬盘插好后&#xff0c;就要进行挂载。在AI的指导下&#xff0c;过程并不顺利。记录如下&#xff1a; 1、检查硬盘是否被识别 安装好硬盘后&#xff0c;运行以下命令来检查Linux系统是否…

涂装协作机器人:重新定义涂装工艺的智能化未来

一、涂装场景的产业变革与核心诉求 1.1 千亿级市场的技术突围战 在汽车制造领域&#xff0c;涂装车间被称为"工业化妆间"&#xff0c;其工艺质量直接影响产品溢价能力。当前行业面临三重挑战&#xff1a; 质量维度&#xff1a;传统人工喷涂存在膜厚波动15μm的行业…

Unity优化篇之DrawCall

当然可以&#xff01;以下是完整、详尽、可发布的博客文章&#xff0c;专注讲解 Unity 的静态合批与动态合批机制&#xff0c;并详细列出它们对 Shader 的要求和所有限制条件。文章结构清晰、技术深度足够&#xff0c;适合发布在 CSDN、掘金、知乎等技术平台。 urp默认隐藏动态…

Electron桌面应用下,在拍照、展示pdf等模块时,容易导致应用白屏

Electron 应用白屏问题分析与解决方案 Electron 应用中拍照、PDF展示等模块导致白屏的常见原因通常与内存泄漏、渲染进程崩溃或资源加载超时有关。以下是具体排查与解决方法&#xff1a; 检查内存泄漏 项目中&#xff0c;分析代码&#xff0c;高频操作或未释放的资源可能导致…

比对++Hex or Bin文件

用NotePad 安装 ​​ Hex-Editor 插件 1.1参考方法路径https://cloud.tencent.com/developer/article/2311013 1.2 下载 Hex-Editor.dll文件路劲 https://sourceforge.net/projects/npp-plugins/ 比对 2.1, 显示Bin 插件/Hex Editor/View in Hex 2.2 插件/Compare(运行很不流…

以STM32H7微控制器为例,简要说明stm32h7xx_it.c的作用

在STM32开发中&#xff0c;stm32h7xx_it.c文件是中断服务例程&#xff08;ISR, Interrupt Service Routine&#xff09;的核心实现文件&#xff0c;其作用与产生的逻辑如下&#xff1a; 一、文件的核心作用 中断处理入口 该文件定义了STM32H7微控制器所有硬件中断和异常的处理函…

若依框架页面缓存查询条件后,切换页面想重新请求一下数据

因为框架使用了Keep-Alive缓存组件&#xff0c;所以使用onActivated钩子 import { onActivated } from vue;// 当组件从缓存中重新激活时 onActivated(() > {getList(); });

智能心理医疗助手开发实践:从技术架构到人文关怀——CangjieMagic情感医疗应用技术实践

作为一名长期耕耘在医疗健康领域的技术开发者&#xff0c;我至今仍清晰地记得三年前那个深夜——当我调试的心理健康AI第一次对用户的情绪崩溃做出恰当回应时&#xff0c;整个团队爆发的欢呼声。那一刻&#xff0c;我深刻意识到技术不只是冰冷的逻辑&#xff0c;更可以成为温暖…