操作符详解(下)

目录

下标访问[ ]、函数调用()

[ ] 下标引用操作符

函数调用操作符

结构成员访问操作符 

结构体成员的直接访问

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

优先级

结合性

整型提升

算术转换


下标访问[ ]、函数调用()

[ ] 下标引用操作符

操作数:一个数组名 + 一个索引值

操作符详解(下)_第1张图片

函数调用操作符

接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数。 

如下图:操作符详解(下)_第2张图片

结构成员访问操作符 

要想弄明白这个,就得知道结构体是什么?C语言已经提供了内置类型,如:char、short、int、long、float、double等,但是只有这些内置类型还是不够的,假设我想描述学生,描述一本书,这时单一的内置类型是不行的。描述一个学生需要名字、年龄、学号、身高、体重等;描述一本书需要作者、出版社、定价等。C语言为了解决这个问题,增加了结构体这种自定义的数据类型,让程序员可以自己创造适合的类型。  结构体是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量,如: 标量、数组、指针,甚至是其他结构体。数组与其定义是比较相似的,数组是一组相同元素的集合。

结构体的关键字是:struct。

下面的图就是结构体创建的语法。

操作符详解(下)_第3张图片

既然已经知道创建结构体的语法了,那我们不妨就来创建一个结构体变量。

例如:我们要描述一个学生,我们就可以用姓名,年龄,学号,身高,体重等来描述。

代码演示:

操作符详解(下)_第4张图片

全局是在括号外定义的;局部是在括号内定义的。

定义完后,我们也可以再初始化变量。 

操作符详解(下)_第5张图片

如果不加 f 后缀,那么编译器会把它当成double类型的值。 

如果是结构体中包含结构体,那么我们在初始化时,就要将那个被包含的结构体也是按照结构体的方法来初始化的(用{ }),那这个初始化模型就是:{ { ...} ,...}。

代码演示:操作符详解(下)_第6张图片

结构体成员的直接访问

结构体成员的直接访问是通过点操作符(.)访问的。点操作符有两个操作数。一个是结构体变量,一个是结构体成员变量。

代码演示:操作符详解(下)_第7张图片

结构体成员的间接访问

这个在结构体中细讲。

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

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

优先级

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

举例: 2 * 4 + 6  我们想要计算出这个表达式的结果,就得先知道这个表达式的运算符优先性,这个表达式的运算符优先性是 * 大于 + 那么这个表达式的运算顺序是先算2 * 4,再算+ 6的结果。

结合性

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

举例:2 + 4 - 6  我们想要计算出这个表达式的结果,就先得知道这个表达式中运算符的优先性,因为 + 和 - 号的优先级是相同的,所以我们就得看它们的结合性,它们都是左结合运算符,所以从左到右执行,先计算2 + 4,再算- 6的结果。

运算符的优先级顺序很多,下面是部分运算符的优先级顺序(按照优先级从高到低排列),建议大概记住这些操作符的优先级就行,其他操作符在使用的时候查看下面表格就可以了。

• 圆括号( () )

• 自增运算符( ++ ),自减运算符( -- )

• 单目运算符( + 和 - )

• 乘法( * ),除法( / )

• 加法( + ),减法( - )

• 关系运算符( < 、 > 等)

• 赋值运算符( = )

由于圆括号的优先级最高,所以可以使用它改变其他运算符的优先级。

下面是完整的。

操作符详解(下)_第8张图片

参考:https://zh.cppreference.com/w/c/language/operator_precedence 

整型提升

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

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

上面说了怎么多,其实就是在说:如果在运算时,有小于一个整形数据长度的(4个字节,也就是32个比特位),就要提升为一个整形数据该有的长度,再去运算。并且运算之后,如果存储在一个小于整形的数据中那么那个数据就要按照它的类型对应的字节来截断这个提升之后的整形。 

举例:

操作符详解(下)_第9张图片

如何进行整体提升呢?

1. 有符号整数提升是按照变量的数据类型的符号位来提升的。

2. 无符号整数提升,高位补0。

操作符详解(下)_第10张图片

操作符详解(下)_第11张图片

算术转换

如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另⼀个操作数的类型,否则操作就无法进行。

下面的层次体系称为寻常算术转换。

long double

double

float

unsigned long int

long int

unsigned int

int

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

例如:int类型和double类型计算,会先将int转换为double类型 。

你可能感兴趣的:(C语言,c语言)