1、结构体的基本使用:
定义形式:
<pre name="code" class="objc">struct 结构体名
{
类型名1 成员名1;
......
类型名n 成员名n ;
};
struct是关键字,是结构体类型的标志
例如:
#include<stdio.h>
/*
数组:只能由多个相同类型的数据构成
结构体:可以由多个不同类型的数据构成
*/
int main()
{
//1.定义结构体类型
struct Person
{
//里面的三个变量,可以称为是结构体的成员或者属性
int age; //年龄
double height; //身高
char *name; //姓名
};
//2.根据结构体类型,定义结构体变量
struct Person p = {20,1.55,"jack"};
p.age = 20;
p.name = "rose";
printf("age = %d,name = %s,height = %f\n",p.age,p.name,p.height);
struct Person p2 = {.age = 30,.name = "rose",.height = 1.62};
//这样是错误的,只能在定义的时候赋值
// struct Person p2;
// p2 = {30,1.67,"jack"};
return 0;
}
2.结构体变量的三种定义方式:
先定义结构体类型在定义结构体变量
定义结构体类型的同时,定义结构体变量
直接定义结构体类型变量,省略类型名
#include <stdio.h>
/*
1.定义结构体变量的3种方式
1> 先定义类型,再定义变量(分开定义)
struct Student
{
int age;
};
struct Student stu;
2> 定义类型的同时定义变量
struct Student
{
int age;
} stu;
struct Student stu2;
3> 定义类型的同时定义变量(省略了类型名称)
struct
{
int age;
} stu;
2.结构体类型的作用域
1> 定义在函数外面:全局有效(从定义类型的那行开始,一直到文件结尾)
2> 定义在函数(代码块)内部:局部有效(从定义类型的那行开始,一直到代码块结束)
*/
// 从这行开始,一直到文件结尾,都是有效(跟全局变量一样)
struct Date
{
int year;
int month;
int day;
};
int a;
void test2()
{
struct Date
{
int year;
};
// 这里使用的是test2函数内部的struct Date类型
struct Date d1 = {2011};
// 结构体类型也是有作用域,从定义类型的那一行开始,一直到代码块结束
struct Person
{
int age;
};
struct Person p;
a = 10;
}
int main()
{
struct Date d1 = {2009, 8, 9};
test2();
// 不能使用test2函数中定义的类型
// struct Person p2;
return 0;
}
// 定义结构体变量
void test()
{
// 定义结构体变量的第3种方式
struct {
int age;
char *name;
} stu;
struct {
int age;
char *name;
} stu2;
/*结构体类型不能重复定义
struct Student
{
int age;
};
struct Student
{
double height;
};
struct Student stu;
*/
/* 错误写法:结构体类型重复定义
struct Student
{
int age;
double height;
char *name;
} stu;
struct Student
{
int age;
double height;
char *name;
} stu2;c
*/
/*
这句代码做了两件事情
1.定义结构体类型
2.利用新定义好的类型来定义结构体变量
*/
// 定义变量的第2种方式:定义类型的同时定义变量
/*
struct Student
{
int age;
double height;
char *name;
} stu;
struct Student stu2;
*/
/*
// 定义变量的第1种方式:
// 1.类型
struct Student
{
int age;
double height;
char *name;
};
// 2.变量
struct Student stu = {20, 1.78, "jack"};
*/
}
3.结构体内存分析:
#include<stdio.h>
int main()
{
struct Student
{
int age; //4个字节
char *name; //8个字节
};
struct Student stu;
stu.age= 20;
stu.name = "jack";
//补齐算法(对齐算法) 结构体所占存储空间为最大成员字节数的倍数 8+4 =12,自动补齐16
int s = sizeof(stu);
printf("%d\n",s); //输出结果为16
return 0;
}
//结构体的内存细节
void test()
{
//1.定义结构体类型(并不会分配存储空间)
struct Date
{
int year;
int month;
int day;
};
//2.定义结构体变量(真正分配存储空间)
struct Date d1 = {2014,4,10};
struct Date d2 = {2012,8,9};
//会将d1所有成员变量的值对应地赋值给d2的所有成员
d2 = d1;
d2.year = 2010; //会只改变d2的的值
//输出结果只有d2的year发生改变,其他都一样
printf("%d - %d - %d\n ",d1.year,d1.month,d1.day);
printf("%d - %d - %d\n ",d2.year,d2.month,d2.day);
/*
printf("%p - %p - %p\n ",&d1.year,&d1.month,&d1.day);
int s = sizeof(d1);
printf("%d\n",s);*/
}
定义结构体类型,只是说明了该类型的组成情况,并没有给它分配存储空间,就像系统不为int类型本身分配空间一样。只有当定义属于结构体类型的变量时,系统才会分配存储空间给该变量
4.结构体数组:
和结构体一样,结构体数组同样有3种定义形式:
<span style="color:#999900;">定义方式1:</span>
<span style="color:#999900;">struct Student {
char *name;
int age;
};
struct Student stu[5]; </span>
<span style="color:#999900;">定义方式2:</span>
<span style="color:#999900;">struct Student {
char *name;
int age;
} stu[5]; :</span>
定义方式3:
<span style="color:#999900;">struct {
char *name;
int age;
} stu[5]; </span>
结构体数组的初始化,和普通数组的用法是一样的,可以用数组的下标访问每一个结构体元素
#include<stdio.h>
int main()
{
struct RankRecord
{
int no; //序号
char *name; //名称
int score; //积分
};
/*
struct RankRecord r1 = {1, "jack",600};
struct RankRecord r2 = {2, "tack",500};
struct RankRecord r3 = {3, "make",200};
*/
//int ages[3] = {29,16,15};
//对齐算法
//能存放3个结构体变量,每个结构体变量占16个字节
struct RankRecord records[3] =
{
{1,"jack",600},
{2,"take",500},
{3,"make",200}
};
records[0].no = 5;
//错误写法
//records[0] = {4,"rose",900};
for (int i = 0; i<3; i++)
{
printf("%d\t%s\t%d\n",records[i].no,records[i].name,records[i].score);
}
return 0;
}
5.指向结构体的指针:
每个结构体都有自己的存储空间,因此指针也可以指向结构体变量
结构体指针变量的定义形式:struct 结构体名称 *指针变量名
3种访问结构体成员的方式:
结构体变量名.成员名
(*指针变量名).成员名
指针变量名->成员名
#include<stdio.h>
int main()
{
struct Student
{
int no;
int age;
};
//结构体变量
struct Student stu = {1,20};
//指针变量p用来指向struct Student类型的数据
struct Student *p;
//指针变量p指向来stu变量
p = &stu;
//第一种方式
printf("age= %d,no =%d\n",stu.age,stu.no);
//第二种方式
printf("age=%d,no =%d\n",(*p).age ,(*p).no);
//第三种方式
printf("age=%d,no =%d\n",p->age,p->no);
return 0;
}
枚举:当一个变量有几个固定的可能取值时,可以将这个变量定义为枚举类型。
比如,可以用一个枚举类型的变量来表示季节,因为季节只有4种可能的取值:春天、夏天、秋天、冬天。
枚举类型的定义:
一般形式为:enum 枚举名 {枚举元素1,枚举元素2,……};
enum Season {spring, summer, autumn, winter};
枚举变量的定义:
先定义枚举类型,再定义枚举变量
enum Season {spring, summer, autumn, winter};
enum Season s;
定义枚举类型的同时定义枚举变量
enum Season {spring, summer, autumn, winter} s;
省略枚举名称,直接定义枚举变量
enum {spring, summer, autumn, winter} s;
枚举元素的值取决于定义时各枚举元素排列的先后顺序。默认情况下,第一个枚举元素的值为0,第二个为1,依次顺序加1。
枚举变量的赋值:
可以给枚举变量赋枚举常量或者整型值
enum Season {spring, summer, autumn, winter} s;
s = spring; // 等价于 s = 0;
s = 3; // 等价于 s = winter;