做网站为什么很复杂,怎么描述网站,泰安网站建设企业,平面设计案例网站0.问题引入 C语言是允许程序员定义自己的组合类型 构造类型 》 数组 结构体 枚举 共用体/联合体 …0.问题引入 C语言是允许程序员定义自己的组合类型 构造类型 》 数组 结构体 枚举 共用体/联合体 现实世界的物体需要抽象成计算机语言中的数据类型对象 学生 学号 int num; 姓名 char name[32]; 性别 char gender; 年龄 int age ..... 把这些物体的属性组合到一个数据类型中去用来表述“学生”这样的类型 结构体
1.结构体 自定义的一种类型 1.1 struct 结构体名 { 成员类型1 成员名1 成员类型2 成员名2 .... 成员类型n 成员名n }; 结构体类型是由多个成员构成而且每个成员都有自己的类型(只要是合法的类型都可以) 不同的成员类型可以相同但是成员名不能相同 struct 结构体名 定义的新类型的名字。 struct student { ...... }; struct student 是我们新定义的类型名 这样的类型是用来描述”学生“的 定义变量 变量的类型 变量名; struct student s ; // s就是一个结构体变量 // typeof(s) struct student 成员类型1成员类型2..... 只要是c语言中合法的类型都可以。 可以是基本类型/构造类型/指针...... “成员名1成员名2....“ 只要符合c语言标识符的规定成员名之间不能相同。 例子 构造一个”学生“这样的结构体类型。 ”学生“ 学号姓名性别年龄成绩 struct student { int num; //学号 char name[32];//姓名 char gender; // 性别 int age // 年龄 float score ;// 成绩 }; 上面的语句构造了一个新的类型 struct student 并且这个新类型里面包含了 num ,name,gender,age,score这些成员变量。 如果要定义一个新类型的变量s结构体变量 变量的类型 变量名 {初始值}; struct student s { 初始值}; 此时s里面会有一个int类型的num,name..... 问题 这些成员变量在内存中是如何分布的呢 1.2结构体成员的内存布局 1结构体类型所占空间是各个成员变量所占空间之和 2结构体内各个成员变量按他们定义时出现的次序依次排列 1.3结构体变量的引用 结构体内部的成员变量的引用 1 . 域操作符 取某个子成员变量 用法 结构体变量名 . 成员名 例子 struct student s; //(snum,name,gender,....) s.num 115200 ;// write int n s.num; // read s.name s.gender s.age s.score .... 引用成员变量和普通变量是一样的他们既有左值也有右值 可以定义一个指针来保存s的地址 指向对象的类型 * p; typeof(s) *p; struct student *p; //p就是一个结构体指针 p s; //保存了结构体变量s的地址p指向s 想通过指针p来访问s里面的成员变量 2(*结构体指针).成员变量名 *p. num ..... 3- 结构体指针 - 成员变量名 练习 1.定义一个结构体类型来描述一个日期年月日 再定义一个结构体类型来描述一个学生姓名成绩出生年月日年龄 请大家再main函数中定义一个学生类型的变量 从键盘给这个结构体变量的成员赋值 再输出这个结构体变量中各个成员的信息。 //日期 struct date { int year; int month; int day; }; struct student { char name[32]; int score; struct date birthday; ---- s.birthday.year s.birthday.month s.birthday.day int age; }; int main() { struct student s; scanf(%s %d %d-%d-%d %d, s.name , s.age, s.brithday.year , s.brithday.month, s.brithday.day, s.score); printf(%s %d %d-%d-%d %d\n, s.name , s.age, s.brithday.year , s.brithday.month, s.brithday.day, s.score ); } 1.4初始化结构体变量的方法 定义结构体变量时候就赋值 struct date { int year; int month; int day; }; struct student { char name[32]; int score; struct date birthday; int age; }; 1按照定义时的顺序依次初始化各个成员变量用逗号隔开。 struct student s { yangyang, 88, {2010,12,12}, 13 }; 2不按照顺序 .成员变量名 值 用逗号隔开 struct student s { .score 88, .birthday {2010,12,12}, .... }; 3结构体数组初始化 a,按照数组元素的顺序依次初始化 struct student class[3] { // class[0] { .name xxx, .age xxx, }, // class[1] { xxxxx } }; b,不按照数组元素的顺序。 [下标] 不同编译器情况或限制不一样 struct student class[3] { [1] {xxxxx}, [0] {xxxx}, }; 练习 定义一个结构体来描述一个学生的信息学号成绩姓名出生年月日 从键盘中输入5个学生的信息假设按成绩的降序依次输出每个学生的信息 struct date { int y, m , d; }; struct student { int num; char name[32]; int score; struct date birthday; }; int main() { struct student *pcls (struct student*)malloc(5*sizeof(*pcls)); // p[0] ... p[4] //从键盘给每一个学生进行输入 int i; for(i0;i5;i) { scanf(%d %s %d %d-%d-%d, pcls[i].num, pcls[i].name, pcls[i].score, pcls[i].birthday.y, pcls[i].birthday.m, pcls[i].birthday.d); } //可以按照学生的成绩由大到小排序 int a[5]; //保存pcls元素的下标 // a[0] 成绩最高的那个学生所在数组pcls中的下标 ... a[4] 成绩最低 for(int i 0;i5;i) { a[i] i; } for(int j 1;j5;j) { for(i 0; i 5-j;i) { if(pcls[a[i]].score pcls[a[i1]].score) { struct student s; s pcls[i]; pcls[i] pcls[i1]; pcls[i1] s; } } } for(i0;i5;i) { printf(%d %s %d %d-%d-%d, pcls[i].num, pcls[i].name, pcls[i].score, pcls[i].birthday.y, pcls[i].birthday.m, pcls[i].birthday.d ); } }
2.共用体/联合体 语法 union 共用体名 { 成员类型1 成员名1 成员类型2 成员名2 ...... }; 共用体与结构体最大的区别 结构体所占内存大小是各个成员变量之和 共用体所占内存大小是各个成员变量中所占内存最大的那个 union t { int a; char b; short c; }; sizeof(union t) 4 共用体的存储空间是各个成员之间共用的 同一时刻只能用一个成员变量为了节省内存才提出 共用体 例子 union test { int a; int b; }; sizeof(union test) 4 占四个字节的空间成员变量a和b共用这四个字节。 union test { char a; int b; }; union test t; t.b 256; t.a ? // 0 大端模式和小端模式 CPU寄存器是按bit位来存储信息的 寄存器的数量是非常有限的 我们经常会把寄存器中的数组存储到存储器内存中去 内存不是按bit来寻址按字节编号地址去寻址 如果把寄存器中的内容存储到内存中去那么内存的 低地址到底是保存寄存器中的 低字节还是高字节呢 大端模式 存储器的低地址存放的寄存器的高字节 低地址 --------- 高地址 // 0x12 34 56 78 高字节 --------- 低字节 // 0x12 0x34 0x56 0x78 小端模式 存储器的低地址存放的寄存器的低字节 低地址 --------- 高地址 // 0x12 34 56 78 低字节 --------- 高字节 // 0x78 0x56 0x34 0x12 共用体的存放顺序是所有成员都从低地址开始存放的利用该特性就可以 轻松获得我们的电脑是属于大端模式还是小端模式 练习; 请大家写一个程序验证一下自己的电脑是属于大端模式还是 小端模式 union test { char a; int b; }; int main() { union test t; t.b 1; if(t.a1) { //小端 } else { //大端 } } 小端模式 如下代码请分析程序的运行结果 union test { char a; int b; }; union test t; t.b 255; t.b; printf(%d\n,t.a); //0
3.枚举 把该类型变量所有可能的值 一一列举出来。 所以枚举类型一定是可以列举的值整数值 例子 int weekday; // 星期几 // 1,2,3,4,5,6,7 枚举语句 enum 类型名 { //枚举的具体的值 }; c语言在实现枚举时枚举的具体的值必须要用整数来表示 。 例子 enum weekday { MON 1, TUE 2, }; enum color { RED, // 0 GREEN, //1 YELLOW, // 2 PINK, // 3 LAN, // 4 }; enum color c RED; printf(%d\n,RED);//0 printf(%d\n,c);//0 enum color { RED1, GREEN, //2 YELLOW250, PINK, // 251 LAN, // 252 }; enum color c RED; printf(%d\n,RED); printf(%d\n,c); -------------------------------------- 构造类型 结构体 共用体 枚举 数组 int a[4];//定义了一个数组atypeof(a) int [4]
4.typedef typedef 用来声明一个新类型 来替换一个已经有的类型
语法 typedef 现有的类型名 新类型名 新类型名 就和 现有的类型名 类型是一样的 例子 struct student { }; typedef struct student STU; STU s; struct student s; typedef struct student { }STU; -------------------------------- int num[100];//定义了一个数组数组名为num //typedef int[100] type_num; typedef int type_num[100]; type_num:新的类型名像num这样的类型 ---》int [100] 假设让你定义一个和num一样类型的变量a typeof(num) a; type_num a; int a[100]; typedef 总结 编程定义一个新类型。 int a// a是一个变量 typedef int a; //a就是一个类型名像int一样的类型
5.字节对齐问题 cpu底层为了访问的效率一般会要求任何对象的地址必须是对齐的 自然对齐: 数据地址是数据长度的倍数 sizeofint 4 int a a 不是4的倍数的话a不是自然对齐 sizeof(short) 2 short a; a 不是2的倍数的话a就不是自然对齐 n---字节对齐 地址是n的倍数n一般为2的x次幂 如 4 - 字节对齐 8 - 字节对齐 ...... 结构体的每一个成员变量通常会有一个默认的对齐方式----自然对齐 struct test { char a; // a的地址必须是1的倍数 int b; // b的地址必须是4的倍数 }; sizeof (struct test) ?8 a _ _ _ b b b b struct test { char a; // short b;// int c; // 4 }; sizeof(struct test) ? //8 struct tese 是几字节对齐 在64bits x86的编译器中 GNUgcc char --- 1字节对齐 short --- 2字节对齐 int --- 4字节对齐 long --- 8字节对齐 float --- 4字节对齐 double--- 8字节对齐 ..... 指针类型 --- 8字节对齐 练习 struct MixedData { char D1; short D2; int D3; char D4; }; sizeof(struct MixedData)? // 12 D1 _ D2 D2 D3 D3 D3 D3 D4 _ _ _ D1 _ D2 D2 D3 D3 D3 D3 D4 _ _ _ --------------------------------- struct FinalPad { float x; char n[1]; }; sizeof(struct FinalPad) ? 8 x x x x ----------------------------------- struct FinalPadShort { short x; char n[3]; }; sizeof(struct FinalPadShort)? 6 x x _ n0 n1 n2 ------------------------------------ struct MixeData { char D1; short D2; int D3; char D4; }; s _ _ _ D1 _ D2 D2 D3 D3 D3 D3 D4 _ _ _ struct test { char s; // 1字节对齐 struct MixeData m;//4字节对齐 }; 结构体是按照最大的原始类型的对齐方式对齐。 sizeof(struct test) ? 16
以下对枚举类型名的定义中正确的是 (B)
A enum a{one,two,three};
B enum a {one9,two-1,three};
C enum a{one,two,three};
D enum a {one,two,three};
以下程序的执行结果是小端模式 266
#include stdio.h
union un
{
int i;
char c[2];
};
void main()
{
union un x;
x.c[0]10;
x.c[1]1;
printf(\n%d,x.i);
}
以下程序的运行结果为 (80)
typedef union student
{
char name[10];
long sno;
char sex;
float score[4];
}stu;
main()
{
stu a[5];
printf(%d\n,sizeof(a));
}