目录
1. 定义:
2. 格式:
3. 结构体变量
3.1. 概念:
3.2. 格式:
1) 先定义结构体,在定义结构体变量
2) 定义结构体的同时,定义结构体变量
3) 缺省结构体名定义结构体变量
4. 赋值
4.1. 定义变量时直接用大括号赋值
4.2. 定义变量时未初始化,然后对变量单独赋值
4.3. 点等法赋值
5. 访问
6.重定义 typedef
6.1. 定义结构体的同时进行重定义
6.2. 先定义结构体,然后重定义
补充
结构体数组
1. 概念:
2. 格式:
2.1. 定义结构体的同时定义结构体数组
2.2. 先定义结构体,然后定义结构体数组
3. 初始化:
3.1. 定义结构体数组同时赋值
3.2. 先定义结构体数组,在对结构体数组的每一个元素分别赋值
4. 结构体数组大小
5. 结构体数组输入输出(for循环)
结构体指针
1. 概念:
2. 格式:
3. 赋值:
4. 结构体指针的大小
总结:
练习:
一、 结构体大小
遵循结构体字节对齐原则
1. 什么是字节对齐
2. 字节对齐原则
练习
3. 为什么要进行字节对齐?
1. 定义:
用户自定义的数据类型,在结构体中可以包含若干个不同数据类型的成员变量(也可以相同),使这些数据项组合起来反应某一个信息。
2. 格式:
struct 结构体名
{
数据类型 成员变量1;
数据类型 成员变量2;
数据类型 成员变量3;
};
3. 结构体变量
3.1. 概念:
通过结构体类型定义的变量
3.2. 格式:
struct 结构体名 变量名;
1) 先定义结构体,在定义结构体变量
struct结构体名
{
成员变量;
};
struct 结构体名 变量名;
#include <stdio.h>struct student
{int id;int age;char sex;float score;
};int main(int argc, char const *argv[])
{struct student stu;return 0;
}
2) 定义结构体的同时,定义结构体变量
struct 结构体名
{
成员变量;
}变量名;
#include <stdio.h>struct student
{int id;int age;char sex;float score;
} stu; // 这个是全局的int main(int argc, char const *argv[])
{return 0;
}
3) 缺省结构体名定义结构体变量
struct
{
成员变量;
} 变量名;
#include <stdio.h>struct
{int id;int age;char sex;float score;
} stu;int main(int argc, char const *argv[])
{// struct student stu;return 0;
}
4. 赋值
4.1. 定义变量时直接用大括号赋值
#include <stdio.h>struct student
{int id;int age;char sex;float score;
};int main(int argc, char const *argv[])
{struct student stu = {1, 18, ' ', 60};return 0;
}
4.2. 定义变量时未初始化,然后对变量单独赋值
struct student
{int id;int age;char sex;float score;
};int main(int argc, char const *argv[])
{struct student stu;stu.id = 3;stu.age = 23;stu.sex = ' ';return 0;
}
4.3. 点等法赋值
#include <stdio.h>struct student
{int id;int age;char sex;float score;
};int main(int argc, char const *argv[])
{struct student stu = {.id = 3,.age = 19,.score = 72,};return 0;
}
5. 访问
通过 .访问:结构体变量名.成员变量
scanf("%d %d %f", &stu.id, &stu.age, &stu.score);
printf("%d %d %.2f\n", stu.id, stu.age, stu.score);
6.重定义 typedef
typedef int size_t;
typedef int *int_p;
int a == size_t a;
int *p = &a;== int_p p = &a;
6.1. 定义结构体的同时进行重定义
typedef struct student
{int id;int age;char sex;float score;
} STU;STU stu; // == struct student stu
6.2. 先定义结构体,然后重定义
struct student
{int id;int age;char sex;float score;
};
typedef struct student STU;
STU stu;
补充
typedef struct student
{int id;int age;char sex;
}STU;STU stu = {1, 2, ''};
STU *p = &stu;typedef struct student
{int id;int age;char sex;
}STU, *STUP;STU stu = {1, 2, ''};STUP p = &stu; // == STU *p = &stu;
结构体数组
1. 概念:
结构体类型相同的变量组成的数组
2. 格式:
2.1. 定义结构体的同时定义结构体数组
struct student
{int id;int age;int score;
} stu[3];
2.2. 先定义结构体,然后定义结构体数组
struct student
{int id;int age;int score;
};struct student stu[3];
3. 初始化:
3.1. 定义结构体数组同时赋值
struct student
{int id;int age;int score;
} stu[3] = {{1, 20, 36},{2, 19, 27},{3, 23, 45},
};
3.2. 先定义结构体数组,在对结构体数组的每一个元素分别赋值
struct student
{int id;int age;int score;
} stu[3];stu[0].id =1;
stu[0].age = 20;
stu[1].id = 2;
4. 结构体数组大小
sizeof(结构体数组名);
元素个数 *结构体类型大小
5. 结构体数组输入输出(for循环)
struct student
{int id;int age;int score;
} stu[3];int main(int argc, char const *argv[])
{for (int i = 0; i < 3; i++){scanf("%d %d %d", &stu[i].id, &stu[i].age, &stu[i].score);}for (int j = 0; j < 3; j++){printf("%d %d %d\n", stu[j].id, stu[j].age, stu[j].score);}
}
练习:创建一个名为student的结构体数组,包含学号,姓名,分数,(数据类型自己定义),从终端输入学生的信息并打印分数及格的学生信息(输入3人即可)。
结构体指针
1. 概念:
指向结构体的指针
2. 格式:
struct结构体名*结构体指针名;
#include <stdio.h>struct student
{int id;int age;float score;
}stu1, stu2;struct work
{int id;int age;float score;
}w1, w2;int main(int argc, char const *argv[])
{struct student *p = &stu1;struct student *p2 = &w1; // 错误,结构体类型不匹配return 0;
}
3. 赋值:
格式:结构体指针变量名 ->成员变量名
#include <stdio.h>struct student
{int id;int age;float score;
}stu1, stu2;struct work
{int id;int age;float score;
}w1, w2;int main(int argc, char const *argv[])
{struct student *p = &stu1;struct work *p2 = &w1;p -> id = 2;p -> age = 20;p -> score = 70;printf("%d %d %f\n", p -> id, p -> age, p -> score);return 0;
}(*p).id = 2
4. 结构体指针的大小
本质是指针:4字节
总结:
1. 不能把结构体类型变量作为整体引用,只能对结构体类型变量中的各个成员变量分别引用
2. 如果成员变量本身属于另一种结构体类型,用若干个成员运算符一级级找到最低级的成员变量
3. 可以把成员变量当成普通变量运算
4. 在数组中,数组之间是不能彼此赋值的,结构体变量可以相互赋值
总结:
1. 不能把结构体类型变量作为整体引用,只能对结构体类型变量中的各个成员变量分别引用
2. 如果成员变量本身属于另一种结构体类型,用若干个成员运算符一级级找到最低级的成员变量#include <stdio.h>struct work
{int id;int age;float score;
};struct student
{int id;int age;float score;struct work w1;
}stu1, stu2;int main(int argc, char const *argv[])
{stu1.w1.id = 20return 0;
}3. 可以把成员变量当成普通变量运算
4. 在数组中,数组之间是不能彼此赋值的,结构体变量可以相互赋值
练习:
1. 创建一个结构体数组,数组名为book,结构体成员包含编号,书名,售价(数据类型自己设定)。写一个函数,包含两个形参,分别接收结构体数组的首地址和一个指定的售价,函数的功能为打印结构体数组中售价大于指定售价的书的信息。
2. 给定N个职员的信息,包括姓名、基本工资、浮动工资和支出,要求编写程序顺序从大到小输出每位职员的姓名和实发工资(实发工资=基本工资+浮动工资-支出)
3. 创建一个结构体数组,数组名为student,成员包含学号,姓名,成绩(数据类型自己设定)从终端输入学生信息,封装函数实现按成绩从低到高打印学生信息。
一、 结构体大小
struct stu
{
int num; //4
char ch; //1
short sh; //2
};
遵循结构体字节对齐原则
1. 什么是字节对齐
在实际使用中,访问特定数据类型变量时需要在特定的内存起始地址进行访问,这就需要各种数据类型按照一定的规则在空间上进行排列,而不是顺序地一个接一个地存放,这就是字节对齐
2. 字节对齐原则
a. 在32位系统下会有一个默认value值大小为4字节,和结构体成员中类型最大的字节大小进行比较,按照小的数进行对齐(每次开辟的空间大小)
b. 结构体成员进行对齐时遵循地址偏移量是成员类型大小的整数倍,double类型数据存放在4字节的整数倍上
c. 结构体成员按顺序进行存储,在满足以上条件时,需要填充空字节
练习
20,16
3. 为什么要进行字节对齐?
a. 平台原因:不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。(提高程序的移植性)
b. 性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
c. 内存原因:在设计结构体时,通过对齐规则尽可能优化结构体的空间大小至最小空间