C语言的模型玩具:结构体的使用以及操作符优先级

各位少年,大家好,我是博主那一脸阳光,今天分享结构体的使用,声明以及操作符的使用。
在这里插入图片描述

前言:

如果你想做一块月饼,你要学习它的制作方法,需要准备面粉,白砂糖,奶粉,干果、坚果,冰皮月饼等材料,但我们还需要一个摸具来造成出原型的月饼。

根据我上面的描述大家明白了,做月饼不仅材料和馅料还需要个工具叫做容具,看上图半成品是到了容具之后出现了对应图形,那我们介绍这个有什么用呢?当然有用struct就是相当于一个容具的作用。

struct tag\\(结构体名字)
{member-list;\\(成员列表)
}variable-list;\\(变量列表)

结构体的意义

C语⾔已经提供了内置类型,如:char、short、int、long、float、double等,但是只有这些内置类
型还是不够的,假设我想描述学⽣,描述⼀本书,这时单⼀的内置类型是不⾏的。描述⼀个学⽣需要
名字、年龄、学号、⾝⾼、体重等;描述⼀本书需要作者、出版社、定价等。C语⾔为了解决这个问
题,增加了结构体这种⾃定义的数据类型,让程序员可以⾃⼰创造适合的类型。

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

代码例子

大家看到了结构体肯定想到了一个项目,叫做学生管理系统,今天我给大家分享其中较为重要一点和其制作的思路,好,我们先制作一个模板叫做学生,一个得有名字,学号,年龄,性别。

struct Stu
{char name[20];//名字int age;//年龄char sex[5];//性别char id[20];//学号
}; //分号不能丢
#include<stdio.h>
struct Stu
{char name[20];int age;float score;
}s3={"wangwu",33,66.0f),s4={"翠华",18,100.0};
int main()
{struct Stu s1 = { "aoao",20,95.5f};//局部变量return 0;
}

上面代码中,我们成功的从Stu这个摸具 来创建了一个我们这个代码,但是我们惊讶的发现,我们通过结构体创建了类似数组的东西,这东西就叫做结构体变量

结构体成员的直接访问

结构体成员的直接访问是通过点操作符(.)访问的。点操作符接受两个操作数。比如说我们要先输入学生的成绩或者学好,怎么办呢?这时候我们就需要(.)操作符了。使用如下
`

#include<stdio.h>
struct Stu
{char name[20];int age;float score;
}s3={"wangwu",33,66.0f),s4={"翠华",18,100.0};
int main()
{struct Stu s1 = { "aoao",20,95.5f};//局部变量struct Stu s5=(.score=98.5f, .name"hehe", .age=100.0);return 0;
}

结构体嵌套

#include<stdio.h>
struct Point
{
int x;
int y;
};
struct Data
{
int num;
struct Point p;
};
int main()
{
struct Data d={200,{10,11}};//这块的大括号都是需要用的
printf("numb=%d p.x=%d p.y=%d\n",d.num,d.p.x,d.p.y);//嵌套打印的方法
return 0;
}
.结构成员访问操作符
结构体变量成员名

结构体成员的指针

有时候我们得到的不是一个结构体变量,而是得到一个结构体的指针,如下展示。

struct Stu* ps = &s1;printf("%s %d %f", ps->name, ps->age, ps->score);

指针是什么?
指针另外一个名字叫做地址,和现实中的地址有异曲同工之妙,
比如说某个学校在长江路307号,这很显然就是个地址,哪计算机中的地址也是一样的。
上面代码中:取了s1的地址 &(取地址操作符),然后通过->打印出结构体出来。
在这里插入图片描述

#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个重要的属性:优先级、结合性,这两个属性决定了表达式求值的计算顺序。
例子

3+4*5

上⾯⽰例中,表达式 3 + 4 * 5 ⾥⾯既有加法运算符( + ),⼜有乘法运算符( * )。由于乘法
的优先级⾼于加法,所以会先计算 4 * 5 ,⽽不是先计算 3 + 4 。

优先级:(相邻操作符),优先级高的先执行,优先级低的后执行!
结合性

如果两个运算符优先级相同,优先级没办法确定先计算哪个了,这时候就看结合性了,则根据运算符
是左结合,还是右结合,决定执⾏顺序。⼤部分运算符是左结合(从左到右执⾏),少数运算符是右
结合(从右到左执⾏),⽐如赋值运算符( =
奉上一个C/C++中文版的官网,上面有函数和操作符优先级:https://zh.cppreference.com/w/c/language/operator_precedence
在这里插入图片描述

  • 和 / 的优先级相同,它们都是左结合运算符,所以从左到右执⾏,先计算 5 * 6 ,
    再计算 6 / 2 。
    运算符的优先级顺序很多,下⾯是部分运算符的优先级顺序(按照优先级从⾼到低排列),建议⼤概
    记住这些操作符的优先级就⾏,其他操作符在使⽤的时候查看下⾯表格就可以了。
    • 圆括号( () )
    • ⾃增运算符( ++ ),⾃减运算符( – )
    • 单⽬运算符( + 和 - )
    • 乘法( * ),除法( / )
    • 加法( + ),减法( - )
    • 关系运算符( < 、 > 等)
    • 赋值运算符( = )
    由于圆括号的优先级最⾼,可以使
    ⽤它改变其他运算符的优先级

表达式求值

整型提升

C语⾔中整型算术运算总是⾄少以缺省整型类型的精度来进⾏的。
为了获得这个精度,表达式中的字符和短整型操作数在使⽤之前被转换为普通整型,这种转换称为整
型提升。

(简单意思就是说int类型大小是四个字节,char类型大小一个字节,short类型两个字节,但是编译器都会按int类型大小进行计算)就好比没成年不能进网吧道理一样,最后即使你进去会不会因为不够年龄被踢出来呢?我们接着往下看。

整形提升的意义

在这里插入图片描述

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

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

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

算术转换

如果某个操作符的各个操作数属于不同的类型,那么除⾮其中⼀个操作数的转换为另⼀个操作数的类
型,否则操作就⽆法进⾏。下⾯的层次体系称为寻常算术转换。

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

如果某个操作数的类型在上⾯这个列表中排名靠后,那么⾸先要转换为另外⼀个操作数的类型后执⾏
运算。

问题表达式解析

a*b + c*d + e*f

表达式1在计算的时候,由于 * ⽐ + 的优先级⾼,只能保证, * 的计算是⽐ + 早,但是优先级并不
能决定第三个 * ⽐第⼀个 + 早执⾏。
所以表达式的计算机顺序就可能是:

a*b
c*d
a*b + c*d
e*f
a*b + c*d + e*f
或者
a*b
c*d
e*f
a*b + c*d
a*b + c*d + e*f

上面程序中,可能各位少年有所看不懂。我们总结一下可能计算出的结果有所差异,先乘哪个,先加哪个都有所问题,所以我建议工作中分开来写,或者括号明确优先级。

表达式2

`
//表达式2

c + --c; 
``

同上,操作符的优先级只能决定⾃减 – 的运算在 + 的运算的前⾯,但是我们并没有办法得知, + 操
作符的左操作数的获取在右操作数之前还是之后求值,所以结果是不可预测的,是有歧义的。`

表达式3

``

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

表达式3在不同编译器中测试结果:⾮法表达式程序的结果
在这里插入图片描述

表达式4
#include <sdtio.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(); 中我们只能通过操作符的优先级得知:先
算乘法,再算减法。
函数的调⽤先后顺序⽆法通过操作符的优先级确定。

表达式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编译器执⾏结果:
在这里插入图片描述
VS2022运⾏结果:
在这里插入图片描述
看看同样的代码产⽣了不同的结果,这是为什么?
简单看⼀下汇编代码,就可以分析清楚.
这段代码中的第⼀个 + 在执⾏的时候,第三个++是否执⾏,这个是不确定的,因为依靠操作符的优先
级和结合性是⽆法决定第⼀个 + 和第三个前置 ++ 的先后顺序。
总结
即使有了操作符的优先级和结合性,我们写出的表达式依然有可能不能通过操作符的属性确定唯⼀的
计算路径,那这个表达式就是存在潜在⻛险的,建议不要写出特别负责的表达式。

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

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

相关文章

构建未来学堂:在线教育系统开发技术实践

在当今数字化时代&#xff0c;在线教育系统的开发越发显得至关重要。本文将带你深入了解在线教育系统的开发&#xff0c;涉及到关键的技术实践和代码示例。我们将采用现代化技术栈&#xff0c;为未来学堂的搭建提供实用的指南。 技术栈选择 在开始实际的开发之前&#xff0c…

RX4901CE (RTC模块)

RX4901CE是一个集成了32.768 kHz数字温度补偿晶体振荡器(DTCXO)的RTC模块。高稳定性&#xff0c;低电流消耗&#xff0c;时间戳功能&#xff0c;当外部或内部事件发生时&#xff0c;可以记录多达32个日期和时间&#xff0c;以及基本的RTC功能&#xff0c;如时间和日历&#xff…

Backtrader 文档学习-Order OCO orders

Backtrader 文档学习-Order OCO orders 主要是可以使用订单组的管理策略&#xff0c;使用订单组策略&#xff0c;则一组订单中&#xff0c;有一个符合条件的订单成交&#xff0c;订单组中其他的订单就自动被取消。 1.概述 V1.9.36.116 版本交互式代理支持StopTrail、StopTra…

Spring复习更新中

Spring复习更新中 Bean的生命周期SpringIoc(Inversion of Control)注解 SpringBootSpringMVCSpringCloud 更新中ing JVM/GC复习已更新完 Bean的生命周期 五步 第一步&#xff1a;实例化Bean第二步&#xff1a;Bean属性赋值第三步&#xff1a;初始化Bean第四步&#xff1a;使用…

H.264与H.265的主要差异

H.265仍然采用混合编解码&#xff0c;编解码结构域H.264基本一致&#xff0c; H.265与H.264的主要不同 编码块划分结构&#xff1a;采用CU (CodingUnit)、PU(PredictionUnit)和TU(TransformUnit)的递归结构。 并行工具&#xff1a;增加了Tile以及WPP等并行工具集以提高编码速…

【图形学】贝塞尔曲线理论与实践

贝塞尔曲线&#xff08;Bezier Curve&#xff09;在计算机图形领域应用非常广泛&#xff0c;比如我们 CSS 动画、 Canvas 以及 Photoshop 等都可以看到贝塞尔曲线的身影。 贝塞尔曲线类型 贝塞尔曲线根据_控制点_的数量分为&#xff1a; 一阶贝塞尔曲线&#xff08;2 个控制点…

SpringCloud-Knife4j文档聚合

在微服务架构下&#xff0c;如果给每个微服务都配置文档&#xff0c;那么每个微服务的接口文档都有自己独立的访问地址&#xff0c;这样要一个个打开每个微服务的文档非常麻烦。一般我们会采用聚合的办法&#xff0c;将所有微服务的接口整合到一个文档中&#xff0c;具体做法有…

DDColor:AI图像着色工具,优秀的黑白图像上色模型,支持双解码器!

前言 在数字图像处理领域&#xff0c;图像上色 一直是一个重要的课题。传统的图像上色方法通常需要人工干预&#xff0c;耗时且效果有限。 然而&#xff0c;随着深度学习技术的发展&#xff0c;自动图像上色模型逐渐成为了研究热点。 其中&#xff0c;DDColor 图像上色模型以…

vue3+elementPlus pc和小程序ai聊天文生图

websocket封装可以看上一篇文章 //pc端 <template><div class"common-layout theme-white"><el-container><el-aside><div class"title-box"><span>AI Chat</span></div><div class"chat-list&…

iOS推送通知

文章目录 一、推送通知的介绍1. 简介2. 通知的分类 二、本地通知1. 本地通知的介绍2. 实现本地通知3. 监听本地通知的点击 三、远程通知1. 什么是远程通知2. 为什么需要远程通知3. 远程通知的原理4. 如何做远程通知5. 远程通知证书配置6. 获取远程推送要用的 DeviceToken7. 测试…

代码随想录算法训练营第30天 | 回溯总结 + 3道Hard题目

今日任务 332.重新安排行程 51. N皇后 37. 解数独 总结 总结 回溯总结&#xff1a;代码随想录 回溯是递归的副产品&#xff0c;只要有递归就会有回溯&#xff0c;所以回溯法也经常和二叉树遍历&#xff0c;深度优先搜索混在一起&#xff0c;因为这两种方式都是用了递归。 …

《WebKit 技术内幕》学习之十三(1):移动WebKit

1 触控和手势事件 1.1 HTML5规范 随着电容屏幕的流行&#xff0c;触控操作变得前所未有的流行起来。时至今日&#xff0c;带有多点触控功能已经成为了移动设备的标准配置&#xff0c;基于触控的手势识别技术也获得巨大的发展&#xff0c;如使用两个手指来缩放应用的大小等。…

DAY11_(简易版)VUEElement综合案例

目录 1 VUE1.1 概述1.1.1 Vue js文件下载 1.2 快速入门1.3 Vue 指令1.3.1 v-bind & v-model 指令1.3.2 v-on 指令1.3.3 条件判断指令1.3.4 v-for 指令 1.4 生命周期1.5 案例1.5.1 需求1.5.2 查询所有功能1.5.3 添加功能 2 Element2.0 element-ui js和css和字体图标下载2.1 …

Vulnhub靶场DC-6

攻击机192.168.223.128 靶机192.168.223.134 主机发现:nmap -sP 192.168.223.0/24 端口扫描 nmap -sV -p- -A 192.168.223.134 开启了22 80端口&#xff0c;80是apache 2.4.25 先进入web界面看一下 用ip进不去&#xff0c;应该被重定向到wordy.com vim /etc/hosts 加上 19…

亚信安慧AntDB构建未来数据库典范

亚信安慧AntDB是一款数据库管理系统&#xff0c;它采用全球影响力大、社区繁荣、开放度高、生态增长迅速的PG内核。这款系统具有卓越的性能和稳定性&#xff0c;在全球范围内备受用户青睐。 与此同时&#xff0c;AntDB的社区也是充满活力的&#xff0c;用户可以在社区中交流经…

Vue中使用TypeScript:全面指南和最佳实践

🚀 欢迎来到我的专栏!专注于Vue3的实战总结和开发实践分享,让你轻松驾驭Vue3的奇妙世界! 🌈✨在这里,我将为你呈现最新的Vue3技术趋势,分享独家实用教程,并为你解析开发中的难题。让我们一起深入Vue3的魅力,助力你成为Vue大师! 👨‍💻💡不再徘徊,快来关注…

WebSocket服务端数据推送及心跳机制(Spring Boot + VUE):

文章目录 一、WebSocket简介&#xff1a;二、WebSocket通信原理及机制&#xff1a;三、WebSocket特点和优点&#xff1a;四、WebSocket心跳机制&#xff1a;五、在后端Spring Boot 和前端VUE中如何建立通信&#xff1a;【1】在Spring Boot 中 pom.xml中添加 websocket依赖【2】…

都学Python了,C++难道真的用不着了吗?

都学Python了&#xff0c;C难道真的用不着了吗&#xff1f; 在开始前我分享下我的经历&#xff0c;刚入行时遇到一个好公司和师父&#xff0c;给了我机会&#xff0c;两年时间从3k薪资涨到18k的&#xff0c; 我师父给了一些【C 】学习方法和资料&#xff0c;让我不断提升自己…

单片机介绍

本文为博主 日月同辉&#xff0c;与我共生&#xff0c;csdn原创首发。希望看完后能对你有所帮助&#xff0c;不足之处请指正&#xff01;一起交流学习&#xff0c;共同进步&#xff01; > 发布人&#xff1a;日月同辉,与我共生_单片机-CSDN博客 > 欢迎你为独创博主日月同…

关于axios给后端发送数据的问题

这里需要用的插件&#xff1a;qs.js&#xff0c;是前端给后端发送的数组&#xff0c;需要序列化所以要用到这个插件&#xff0c;这里就提取连接在这里&#xff0c;需要的自提&#xff0c;需要导如进来&#xff0c;别忘记了 链接&#xff1a;https://pan.baidu.com/s/1qyD8v9wfd…