> 技术文档 > #C语言——学习攻略:操作符的探索(二)

#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 doubledoublefloatunsigned long intlong intunsigned intint

--根据顺序可知,操作数的类型在上面这个列表中排名靠后,首先转换为另一个操作数的类型后再执行运算。

3.3 问题表达式解析

3.3.1  表达式1

//表达式的求值部分由操作符的优先级决定。//表达式1a*b + c*d + e*f

-- 注意:计算的时候,*比+的优先级高,只能保证*的计算是比+早。但优先级并不决定第三个*比第一个+早执行。(所以写代码时,最好用括号来区分先后)

3.3.2  表达式2

//表达式2c + --c;

-- c=5

        --如果左操作数的获取在右操作数之前则结果为 5+4=9;
        --如果左操作数的获取在右操作数之后则结果为 4+4=8;

3.3.3  表达式3

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

--表达式3在不同编译器中测试结果:非法表达式程序的结果

3.3.4 表达式4

#include 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 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。

--因为这个代码中的第一个+在执行的时候,第三个++是不是执行,这个不确定。因为依靠操作符的优先级和结合性是无法决定第一个+和第三个前置++的先后顺序。


结语:本篇文章承接上一篇博客,分享了关于操作符剩余知识,一定要好好理解;如果这篇文章对你的学习有帮助的话,欢迎一起讨论学习,你这么帅给个三连吧~~~