C语言第12讲
结构体
结构体可理解为多角度描绘一个复杂对象
例:一本书,从价格,页码总数,书名,都是对书名的描述
结构体的关键字 struct
结构体的创建
struct student/*结构体的名*/
{char name[20];/*结构体成员*/int age;int high;float weight;
};/*括号外需要冒号结尾*/
也可以自己在括号后跟上需要创建多少结构体变量
struct student/*结构体的名*/
{char name[20];/*结构体成员*/int age;int high;float weight;
}s1,s2,s3;/*括号外需要冒号结尾*/
结构创建的位置会决定,该结构体是全局还是局部和变量一般,再函数(main)中局部,不在函数中为全局
结构体的初始化
//按顺序初始化
struct student s1/*结构体变量的名*/ = { "ZhangSan",18,177,161 };
//指定顺序初始化
struct student s2 = { .age = 21, .high = 171, .weight = 188, .name = "WangWu" };
指定初始化时需用到 "." ,点后更成员名
结构体套结构体
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>struct S
{int a;int b;
};struct M
{struct S s;char c;int* p;
};int main()
{return 0;
}
出现结构体套结构体的情况初始化的方式和下方一般
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>struct S
{int a;int b;
};struct M
{struct S s;char c;int* p;
};int main()
{struct M m = { {10,20},'w',NULL };return 0;
}
括号中的括号就是用来初始化嵌套在结构体中的结构体的
打印结构体
结构体的打印需要用上 " . "
struct S
{int a;int b;
};struct M
{struct S s;char c;int* p;
};int main()
{struct M m = { {10,20},'w',NULL };printf("%d %d %c %p", m.s.a, m.s.b, m.c, m.p);return 0;
}
打印结构体的格式为 m(结构体变量名) . (结构体成员名)
打印嵌套结构体格式为 m(结构体变量名) . s(结构体变量名) . (嵌套的结构体成员名)
优先级和结合性
结合性
大部分运算符是左结合(从左到右执行)
少部分是右结构(从右到左执行)
表达式求值
整型提升
int main()
{char a = 3;char b = 127;char c = a + b;return 0;
}
当低于一个 int 类型的内存进行运算时会出现整形提升
char c = a + b;
a 和 b会发生整型提升
a(补):00000011
b(补):0111 1111
整型提升的规则
1.有符号位整数提升是按照变量的数据类型的符号位来提升
2.无符号整型提升,高位补0
a 和 b 发生整型提升
a:00000000 00000000 00000000 00000011
b:00000000 00000000 00000000 0111 1111
a + b:00000000 00000000 00000000 1111 1101
a + b存入时c会截断,因为c类型为char
c = 1111 1101
char的类型是 signed char 还是 unsigned char 取决与编译器
算术转换
如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数装换为另一个操作数的类型,否则就无法进行
1.long double
2.double
3.float
4.unsigned long int
5.long int
6.unsigned int
7.int
如果某个操作数的类型在上面这个列表中排名靠后,那么首先要装换为另一个操作数的类型后执行运算
问题:char + double
运算中 char 先整型提升成 int ,但 int 和double 类型不同,int 转换成 double后再进行最终计算
问题表达式
1. a * b + c * d + e * f;
2.c + --c;
3.( int i = 1, int ret = (++i) + (++i) + (++i) )
由上我们可以知道,即使有了操作符的优先级和结合性,我们写出的表达式依然有可能不能通过操作符的属性确定唯一的计算路径