结构体
结构体,就是一种自定义的数据类型。
说是数据类型,意思就是,跟其他的基本数据类型一样,可以像基本数据类型一样,定义变量。
例如:
与int i = 20;一样,我们如果自定义了一个结构体,名字叫做student,那么意思就是,我们有一个student类型,可以定义一个student类型的变量:student s = {…..};
结构体的声明:
struct student{
char name[20];
int age;
};
如上面的例子所说的,我们用结构体的关键字:struct 来规定 student 类型,花括号里是student类型的成员变量,这些变量都是基本数据类型修饰的变量,可以是普通变量,可以是数组。
注意的是:成员变量不能赋初值。(可以这样想,一个数据类型,怎么能给值?)
一些例子:
#import <Foundation/Foundation.h>
//这个时候,我们已经自定义好了一个CPoint类型
//这只是个类型,没有初值
struct CPoint{
//不能赋初值,会报错
// float x = 0;
// float y = 0;
//成员变量
float x;
float y;
};//结构体后面有分号,不能丢掉。
int main(int argc, const char * argv[]){
// //创建结构体变量,并按顺序赋值
// struct CPoint p = {1.5,2.5} ;
// //打印结构体,得一个一个打印出来。
// printf("%f",p.x);//1.50000
// printf("%f",p.y);//2.50000
return 0;
}
结构体定义:
例子里已经声明了一个CPoint结构体类型,里边有两个成员变量:float型的x和y。我们在main()函数里,对CPoint结构体进行定义变量:
// //创建结构体变量,并按顺序赋值
struct 结构体名 变量名 = {初值};
// struct CPoint p = {1.5,2.5} ;
注意:
初始化:开辟空间时,把值赋上,然后变量可以直接使用
赋值:开辟玩空间后,再往变量里赋值。但是不能对已经开辟好的结构体定义的变量里整个赋值。
//struct test{
// int num;
//};
int main(int argc, const char * argv[]){
// struct test t1 = {1};
// t1 = {222};//这里会报错
// return 0;
}
结构体的使用:
结构体的使用,通过我们定义的变量p来访问成员变量x和y。形式为:
p.x和p.y。
// //打印结构体,得一个一个打印出来。
// printf("%f",p.x);//1.50000
// printf("%f",p.y);//2.50000
一些练习:
#import <Foundation/Foundation.h>
//这个时候,我们已经自定义好了一个CPoint类型
//这只是个类型,没有初值
struct CPoint{
//不能赋初值,会报错
// float x = 0;
// float y = 0;
//成员变量
float x;
float y;
};//结构体后面有分号,不能丢掉。
//练习
//定义一个学生的结构体
struct Student {
short num;//学号
char name[20];//姓名
char sex;//性别
float score;//分数
};
//考虑定义一下结构体
//汽车
struct car {
char brand[20];
int c_number ;
int seats;
float price;
};
//人
struct person{
char name[20] ;
char sex[4];
};
//电脑
struct computer{
char brand[20];
float price;
char cpu[20];
int disk;
};
//书
struct book {
char bookName[20];
char isbn[50];
char publish[50];
char publishDate[20];
float price;
};
int main(int argc, const char * argv[]){
// //创建结构体变量,并按顺序赋值
// struct CPoint p = {1.5,2.5} ;
// //打印结构体,得一个一个打印出来。
// printf("%f",p.x);//1.50000
// printf("%f",p.y);//2.50000
// struct Student s = {1,"王铁柱",'m',99};
// //同类型结构体之间可以直接赋值。
// struct Student s1 = s;
// //吧s1的所有成员变量打印出来。
// printf("%d\n",s1.num);
// printf("%s\n",s1.name);
// printf("%c\n",s1.sex);
// printf("%.1f\n",s1.score);
// //不要把字符串赋值给字符变量(若写字符串,则要用字符数组)
// struct person p1 = {"王大锤","男"};
// //结构体一旦创建好之后,字符数组成员变量不能再直接赋值了,需要使用strcpy();
//// p1.name = "田二牛";//报错
// strcpy(p1.name, "田二牛");
// printf("%s",p1.name);
return 0;
}
创建的结构体变量,赋初值时,要按成员变量的顺序来赋初值。
相同类型的结构体,可以直接把另外一个结构体直接赋值给这个结构体。
若是再创建结构体时,成员变量需要用到字符串,则应该定义一个char型数组,而不能直接将字符串赋值给字符型变量。结构体一旦创建好之后,字符数组成员变量不能再直接赋值了,需要使用strcpy();
匿名结构体:
匿名结构体,没有名字,只能在定义结构体的时候,定义变量。如果再创建一个结构体的同时,没有定义结构体变量,那么这个匿名结构体就算一个没有用的结构体。
struct{
//成员变量
char name[20];
}p1 = {"刘哇"},p2 = {"小金刚"};//匿名结构体,再花括号后面配上一个结构体变量,并且可以直接定义多个变量,赋值。。
typedef:
typedef 这个关键字是为了一个已经有的类型重新取一个别名。
Typedef有两个作用:
1、提示一下,定义出来的变量是干什么用的。
typedef int age;//给int类型取别名age,提示这个类型是用来放年龄age的。
2、简化类型
typedef struct student student;//这个是告诉我们,将student这个类型取一个别名student。
简化结构体的类型有两种方法:
(1)、typedef struct student student;
(2)、一边定义我的结构体,一边同时简化我的类型。(作业:20遍)
typedef struct cat{
char color[20];
}Cat;
这种方式,是在声明cat结构体的同时,给它取了一个名字Cat。
简化类型有是好处呢?好处就是不用再在用struct这个关键字。
一些例子:
//练习
//float类型定义成money
typedef float money;
//int类型定义成 height
typedef int height;
//用两种方式
//struct student 定义成student
//1.
typedef struct Student student;
//2.
typedef struct stu{
char name[20];
int age;
}Stu;
//struct Cpoint 定义成Cpoint
//1.
typedef struct CPoint cpoint;
//2.
typedef struct CPoi {
float x;
float y;
}cpoi;
int main(int argc, const char * argv[]){
//使用int的新名字定义变量
age num = 10;
printf("%d",num);
//简化类型。不用再加上struct
Person p2;
//一边定义我的结构体,一边同时简化我的类型。
Cat c1 = {"白色"};
//练习
money money = 100;
height h = 123;
student s = {};
Stu stu = {"王大锤",90};
cpoint cpoint = {1,2};
cpoi cpoi = {3,4};
return 0;
}
结构体内存占用:
结构体的内存占用情况,分为如下几点:
1、当结构体内没有定义任何成员变量时,这个结构体的占内存为0。
2、分配空间按照成员变量中,最大的分配。逐个使用。
3、内存对齐原则。(因此再定义结构体的时候,占内存大的放前面定义,然后逐个减小定义)
第3点说的明白点,就是结构体内定义一个类型变量时,会给这个类型分配固定字节的内存,但是当第二个成员变量的类型占内存更大时,这个第一个变量的内存会自动扩充到跟较大的那个内存一样。又因为,后一个变量类型在前一个变量的空间里,已经放不下,它不会接在前一个变量内存的后面,而是重新开辟一个内存,给自己用。当后面还有其他成员变量类型时,也不会接到这个变量内存的后面,而是重新开辟一个空间,用来放自己,但是开辟的空间还是跟最大的那个变量的类型占的字节一样大。因此如果在第三个变量后面还定义一个较小类型变量时,如果能在第三个变量的内存空间装完,则接在第三个变量内存后面,如果装不完,则开辟另一个空间。
例子:
结构体内,
先定义一个char 型变量(本身1字节),再定义一个double类型变量(本身8字节),则此时char类型空间开辟了8字节,由于double自己本身有8字节,接在char的后面不够装,因此它要开辟一个新的8字节内存。此时,再定义一个int类型的变量(本身4字节),此时会判断一下,再double那还能接下去装我的int吗?由于装不下,此时就会另外开辟一个8字节的内存空间来装int,还剩4个字节,如果再定义第4个char变量,则可以接到int类型的空间中去,还剩下3个字节。后面以此类推。
结构体的嵌套:
结构体的嵌套,就是结构体里有结构体。
例子如下:
#import <Foundation/Foundation.h>
//2015-04-03 16:17:15 北京
//点的结构体
typedef struct cpoint{
float x;
float y;
}cpoint;
//尺寸结构体
typedef struct csize{
float w;
float h;
}csize;
//矩形结构体
//结构体嵌套:结构体里有结构体
typedef struct cRect{
cpoint point;
csize size;
}cRect ;
//练习
typedef struct Student{
int score;
char name[20];
}Student;
int main(int argc, const char * argv[])
{
// //赋值
// cRect r = {{100,100},{50,50}};
// //使用
// printf("%.1f\n",r.point.x);
// printf("%.1f\n",r.point.y);
// printf("%.1f\n",r.size.h);
// printf("%.1f\n",r.size.w);
// cpoint p1 = {10,20};
// cpoint p2 = {30,40};
// cpoint p3 = {50,60};
//结构体数组
//数组中所有元素,都已同一类型
// cpoint pointArray[3] = {p1,p2,p3};
// printf("%.2f\n",pointArray[0].x);
//练习
Student stu1 = {92,"王大锤1"};
Student stu2 = {91,"王大锤2"};
Student stu3 = {89,"王大锤3"};
Student stu4 = {99,"王大锤4"};
Student stu5 = {79,"王大锤5"};
//初始化:开开辟空间时,把值赋上,然后变量可以直接使用
//赋值:开辟玩空间后,再往变量里赋值。
//这两个过程是不一样的。
Student stuArr[5] = {stu1,stu2,stu3,stu4,stu5};
for (int i = 0; i < 5-1; i ++) {
for (int j = 0; j < 5-(i+1); j++) {
if(stuArr[j].score < stuArr[j+1].score){
Student temp;
temp = stuArr[j] ;
stuArr[j] = stuArr[j+1];
stuArr[j+1] = temp;
}
}
}
printf("成绩从高到低为:\n");
for (int i = 0; i < 5 ; i ++) {
printf("%s: %d分\n",stuArr[i].name,stuArr[i].score);
}
printf("成绩最高的人为:%s:%d 分",stuArr[0].name,stuArr[0].score);
return 0;
}
结构体数组:
将多个结构体变量放到数组中,构成结构体数组。其实跟普通的数组一样,但是在遍历的时候,或者按照某个成员变量排序的时候,要注意的就是,比较有结果后,可以反回这个成员变量,也可以反回整个结构体,看个人方便,想要什么信息,就返回声明信息。
struct student students[10] = {0};
可以通过下标访问结构体变量,例如:
students[0].name; // 第⼀个学⽣的姓名
一些练习:
#import <Foundation/Foundation.h>
//2015-04-03 15:03:18 北京
//第一题
//1、创建学生结构体
//2、成员变量有:姓名,年龄,成绩
//3、五娃 17 88
// 六娃 16 70
// 七娃 9 75
//4、找出成绩最高
//5、找出年龄最小
struct student{
char stuname[20];
int age;
int score;
};
//测试内存结构体
typedef struct Test{
//结构体内没有东西的时候,结构体占内存为0.
//结构体内存,有两条规则。
//1、分配空间按照成员变量中,最大的分配。逐个使用。
//2、内存对齐原则。(因此再定义结构体的时候,占内存大的放前面定义,然后逐个减小定义)
}Test;
int main(int argc, const char * argv[])
{
//第一题
//创建三个学生
struct student student1 = {"五娃",17,88};
struct student student2 = {"六娃",16,70};
struct student student3 = {"七娃",9,75};
// int maxScore = 0;
// if (student2.score < student1.score && student3.score < student1.score) {
// maxScore = student1.score;
// printf("成绩最高的是:%s , %d分",student1.stuname,maxScore);
// }
// if (student1.score < student2.score && student3.score < student2.score) {
// maxScore = student2.score;
// printf("成绩最高的是:%s , %d分",student2.stuname,maxScore);
// }
// if (student1.score < student3.score && student2.score < student3.score) {
// maxScore = student3.score;
// printf("成绩最高的是:%s , %d分",student3.stuname,maxScore);
// }
//
// int minAge =20;
//
// if (student2.age < student1.age && student2.age < student3.age) {
// minAge = student2.age;
// printf("\n年龄最小的是:%s , %d岁",student2.stuname,minAge);
// }
// if (student1.age < student2.age && student1.age < student3.age) {
// minAge = student1.age;
// printf("\n年龄最小的是:%s , %d岁",student2.stuname,minAge);
// }
// if (student3.age < student1.age && student3.age < student2.age) {
// minAge = student3.age;
// printf("\n年龄最小的是:%s , %d岁",student3.stuname,minAge);
// }
//student1 和 student2 中分数最高
// struct student temp = student1.score > student2.score ? student1 : student2;
// //temp和student3中分数最高
// struct student max = temp.score > student3.score ? temp : student3;
//
// printf("成绩最高的是:%s , %d分",max.stuname,max.score);
//
//
//
// struct student temp1 = student1.age < student2.age ? student1 : student2;
//
// struct student min = temp1.age < student3.age ? temp : student3;
//
// printf("\n年龄最小的是:%s , %d岁",min.stuname,min.age);
// //sizeof用来计算占内存多少字节。
// int size = sizeof(double);
// printf("%d",size );//8
printf("%lu",sizeof(Test));
return 0;
}