武器大师——操作符详解(下)

目录

六、单目操作符

七、逗号表达式

八、下标引用以及函数调用

8.1.下标引用

8.2.函数调用

九、结构体

9.1.结构体

9.1.1结构的声明

9.1.2结构体的定义和初始化

9.2.结构成员访问操作符

9.2.1直接访问

9.2.2间接访问

十、操作符的属性

10.1.优先性

10.2.结合性

十一、整形提升

结语


六、单目操作符

!、 ++ 、 -- 、 & 、 * 、 + 、 - 、 ~ 、 sizeof 、 ( 类型 )

上述操作符中,我们在前面都说过,只有&和*没有提及,这两个操作符我们会在指针章节详细介绍。

七、逗号表达式

a1,a2,a3,.....an

逗号表达式,就是用多个逗号隔开的多个表达式。

它是按从左到右 的顺序依次执行。整个表达式的结果是最后一个表达式的结果。

eg:

cpp 复制代码
int a = 1;
int b = 2;
int c = (a>b, a=b+10, a, b=a+1);

首先,从左到右依次执行 ,先是a>b,然后把b+10赋给a,a就变成了12,最后再将a+1的值赋给b,这个表达式的值就是整个表达式的值,也就是13,所以c为13。

八、下标引用以及函数调用

8.1.下标引用

我们在数组中曾见过这对中括号,是的,它的名字叫下标引用。

操作数:数组名+索引值

eg:

cpp 复制代码
int arr[10];//创建数组
arr[9] = 10;//实⽤下标引⽤操作符。
[]的两个操作数是arr和9。

8.2.函数调用

这个相信大家也不陌生。

操作数:函数名+参数

问:函数调用最少有几个操作数?

答:一个,只需要一个函数名即可。

cpp 复制代码
#include <stdio.h>
void test1()
{
 printf("hehe\n");
}
void test2(const char *str)
{
 printf("%s\n", str);
}
int main()
{
 test1(); //这⾥的()就是作为函数调⽤操作符。
 test2("hello bit.");//这⾥的()就是函数调⽤操作符。
 return 0;
}

接下来讲点没见过的。

九、结构体

我们今天只是简单介绍,后面还会继续详细介绍结构体(又挖坑)。

9.1.结构体

我们之前学过许多数据类型结构,像short、char、int、double......但只有这些其实远远不够,比如说我想描述一个学生的信息,身高体重各科成绩等等。C语言为了解决这个问题,内置了结构体这种自定义类型,从此之后,我们可以创造出自己想要的类型。

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

9.1.1结构的声明
cpp 复制代码
struct tag
{
 member-list;//成员列表
}variable-list //变量列表

其中tag表述结构体名,花括号里面放着成员列表,也就是要描述对象的各种属性。变量列表用来存放定义为该结构体类型的变量。

cpp 复制代码
struct Stu
{
 char name[20];//名字
 int age;//年龄
 char sex[5];//性别
 char id[20];//学号
}; //分号不能丢
9.1.2结构体的定义和初始化
cpp 复制代码
//代码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};//结构体嵌套初始化

9.2.结构成员访问操作符

9.2.1直接访问

使用方式:结构体变量 **.**成员名

cpp 复制代码
#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;
}

这个点很小,但是很有用!

9.2.2间接访问

有的时候,我们得到的是结构体的地址,

使用方式:结构体指针(地址)->成员名

举例如下:

cpp 复制代码
#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;
}

综合举例如下:

cpp 复制代码
#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;
}

十、操作符的属性

10.1.优先性

参考链接:C 运算符优先级 - cppreference.com

圆括号( () )
• ⾃增运算符( ++ ),⾃减运算符( -- )
• 单⽬运算符( + 和 - )
• 乘法( * ),除法( / )
• 加法( + ),减法( - )
• 关系运算符( < 、 > 等)
• 赋值运算符( = )
由于圆括号的优先级最⾼,可以使⽤它改变其他运算符的优先级。
大概记住这些就够了,其它可以现查表。

10.2.结合性

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

十一、整形提升

C语⾔中整型算术运算总是⾄少以缺省整型类型的精度来进⾏的。

而为了获得这种精度,表达式中的字符型和短整型在使用之前就会被转换为整形,这种转换叫整形提升

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

cpp 复制代码
char a,b,c;
...
a = b + c;

首先,b和c被提升为整形然后运算赋给a。

如何进行整形提升呢?

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

结语

有很多朋友问为什么以武器大师来做标题,这里结尾给大家解释一下,因为我觉得它就像不同人手中不同的工具,比如算数操作符像是数学家手中的计算器,关系操作符像是侦探手中的证据对比工具,逻辑操作符类似于法官手中的判决书,位操作符更像电路工程师的开关和转换器,赋值操作符像是建筑师手中的蓝图和材料......
其实我们学习每样东西都是,虽然有时很抽象,但是我们总能找到解决办法。
"细想全是问题,去做全是答案"。

相关推荐
嵌入式科普几秒前
十三、从0开始卷出一个新项目之瑞萨RZN2L串口DMA接收不定长
c语言·stm32·瑞萨·e2studio·rzn2l
_WndProc1 分钟前
C++ 日志输出
开发语言·c++·算法
qq_4335545410 分钟前
C++ 面向对象编程:+号运算符重载,左移运算符重载
开发语言·c++
数据小爬虫@29 分钟前
如何高效利用Python爬虫按关键字搜索苏宁商品
开发语言·爬虫·python
ZJ_.31 分钟前
WPSJS:让 WPS 办公与 JavaScript 完美联动
开发语言·前端·javascript·vscode·ecmascript·wps
Narutolxy37 分钟前
深入探讨 Go 中的高级表单验证与翻译:Gin 与 Validator 的实践之道20241223
开发语言·golang·gin
Hello.Reader44 分钟前
全面解析 Golang Gin 框架
开发语言·golang·gin
禁默1 小时前
深入浅出:AWT的基本组件及其应用
java·开发语言·界面编程
Code哈哈笑1 小时前
【Java 学习】深度剖析Java多态:从向上转型到向下转型,解锁动态绑定的奥秘,让代码更优雅灵活
java·开发语言·学习
程序猿进阶1 小时前
深入解析 Spring WebFlux:原理与应用
java·开发语言·后端·spring·面试·架构·springboot