一、结构体变量
结构是一些值的集合,这些值称为成员变量。
结构的每个成员可以是不同类型的变量。
声明一个结构体类型的一般形式:
struct 结构体名
{成员列表};
对各成员的声明:
类型名 成员名;
例如:
typedef struct Stu
{
char name[20];//名字
int age;//年龄
char sex[5];//性别
char id[20];//学号
}Stu;//分号不能丢
结构的成员可以是标量、数组、指针,甚至是其他结构体。
1.定义结构体类型变量
- 先声明结构体类型,在定义该类型的变量
例如:
- 再声明类型的同时定义变量
一般形式:
struct 结构体名
{成员表列
}变量名表列;
- 不指定类型名而直接定义结构体类型变量
一般形式为:
struct
{成员表列
}变量名表列;
- 结构体类型与结构体变量是不同的概念
- 结构体类型中的成员名可以与程序中的变量名相同,但二者不代表同一对象
- 对结构体变量中的成员可以单独使用,作用与地位相当于普通变量
2.结构体变量的初始化和引用
在定义结构体变量时,可以对它初始化,即赋予初始值。可以引用这个变量
例如输出它的成员的值
- 初始化列表是用花括号括起来的一些常量,这些常量依次赋给结构体变量中的各成员。
注意:是对结构体变量初始化,而不是对结构体类型初始化
- 可以引用结构体变量中成员的值。结构变量的成员是通过点操作符(.)访问的,点操作符接受两个操作数;结构体指针访问指向变量的成员,指向一个结构体的指针。
- “.”是成员运算符,他在所有的运算符中优先级最高
- 不能企图通过输出结构体变量名来达到输出结构体变量所有成员的值
- 只能对结构体变量中的各个成员分别进行输入和输出
例如:
#include<stdio.h>
struct Stu
{
char name[20];
int age;
};
void print(struct Stu* ps)
{
printf("name = %s,age = %d\n", (*ps).name, (*ps).age);
//使用结构体指针访问指向对象的成员
printf("name = %s,age = %d\n", ps->name, ps->age);
}
int main()
{
struct Stu s = { "zhangsan", 20 };
print(&s);//结构体地址传参
return 0;
}
结果:
name = zhangsan,age = 20
name = zhangsan,age = 20
- 如果成员本身又属于一个结构体类型,则要用若干个成员运算符,一级一级地找到最低的一级。只能对最低级的成员进行赋值或存取以及运算
- student1.num(结构体变量student1中的成员num)
- student1.birthday.month(结构体变量student1中的成员birthday中的成员month)
- 不可以直接用student1.birthday来访问student1变量中的成员birthday,因为birthday本身是一个结构体成员
- 对结构体变量的成员可以像普通变量一样进行各种运算(根据其类型决定可以进行的运算)
例如:
- student2.score=student1.score;(赋值运算)
- sum=student1.score+student2.score;(加法运算)
- student1.age++;(自家运算)
- student1.age++是对(student1.age)进行自加运算,因为“.”运算符的优先级最高
- 同类的结构体变量可以互相赋值
例如:
student1=student2;
- 可以引用结构体变量成员的地址,也可以引用结构体变量的地址
- scanf(“%d”,&student1.num);(输入student1.num的值)
- printf(“%o”,&student1);(输出结构体变量student1的起始地址)
- 不能整体读入结构体变量
- 结构体变量的地址主要用作函数参数,传递结构体变量的地址
例1:
struct Point
{
int x;
int y;
}p1; //声明类型的同时定义变量p1
struct Point p2; //定义结构体变量p2
例2:
//初始化:定义变量的同时赋初值。
struct Point p3 = { x, y };
例3:
struct Stu //类型声明
{
char name[15];//名字
int age;//年龄
};
struct Stu s = { "zhangsan", 20 };//初始化
例4:
struct Node
{
int data;
struct Point p;
struct Node* next;
}n1 = { 10, { 4, 5 }, NULL }; //结构体嵌套初始化
例5:
struct Node n2 = { 20, { 5, 6 }, NULL };//结构体嵌套初始化
二、使用结构体数组
结构体数组在于每个数组元素都是一个结构体类型的数据,它们都分别包括各个成员项
- 定义结构体数组一般形式是:
struct 结构体名
{成员表列
}数组名[数组长度];
- 先声明一个结构体类型(如struct Person),然后在用此类型定义结构体数组:
结构体类型 数组名[数组长度];
- 对结构体数组初始化的形式是在定义数组的后面加上:
={初值表列};
三、结构体指针
结构体指针就是指向结构体变量的指针
如果把一个结构体变量的起始地址存放在一个指针变量中,那么这个指针变量就指向该结构体变量
- 指向结构体对象的指针变量即可指向结构体变量,也可指向结构体数组中的元素
- 指针变量的基类型必须与结构体变量的类型相同
- 例如:struct Student *pt; ——pt可以指向struct Student类型的变量或数组元素
如果p指向一个结构体变量stu,以下三种等价
- stu.成员名(如stu.num);
- (*p).成员名(如( *p).num);
- p->成员名(如p->num)。
可以用指针变量指向结构体数组的元素
1.指向结构体数组的指针
#include<stdio.h>
struct Student
{
int num;
char name[20];
char sex;
int age;
};
struct Student stu[3] = { { 10101, "LL", 'M', 18 }, { 10102, "ZF", 'M', 19 }, { 10104, "WM", 'F', 20 } };
int main()
{
struct Student*p;
printf("No. Name..................sex age\n");
for (p = stu; p < stu + 3; p++)
{
printf("%5d %-20s %2c %4d\n", p->num, p->name, p->sex, p->age);
}
return 0;
}
结果
No. Name…sex age
10101 LL M 18
10102 ZF M 19
10104 WM F 20
- (++p)->num
先使p自加1,然后得到p指向的元素中的num成员值
- (p++)->num
先求得p->num的值(即10101),然后再使p自加1,指向stu[1]
- p是一个指向struct Student类型对象的指针变量,用来指向一个struct Student类型的对象
p的值stu数组的一个元素(如stu[0]或stu[1])的起始地址
- 若一定要将某一成员的地址赋给p,可以用强制类型转换,先将成员的地址转换成p的类型
p=(struct Student*)stu[0].name;
p的值是stu[0]元素的name成员的起始地址。
可以用“printf(“%s”,p);”输出stu[0]中成员name的值。但是,p仍会保持原来的类型。
可以执行“printf(“%s”,p+1);”则会输出stu[1]中name的值。
执行p++时,p的增量是结构体struct Student的长度。
2.用结构体变量和结构体变量的指针作函数参数
将一个结构体变量的值传递给另一个函数,有三个方法:
- 用结构体变量的成员作参数。
注意:实参与形参的类型保持一致
- 用结构体变量作实参。在函数调用期间形参也要占用内存单元。
如果在执行被调用函数期间改变了形参(也就结构体变量)的值,该值不能返回主调函数
- 用指向结构体变量(或数组元素)的指针作实参,将结构体变量(或数组元素)的地址传给形参
例如:
struct S
{
int data[1000];
int num;
};
struct S s = {{1,2,3,4}, 1000};
//结构体传参
void print1(struct S s)
{
printf("%d\n", s.num);
}
//结构体地址传参
void print2(struct S* ps)
{
printf("%d\n", ps->num);
}
int main()
{
print1(s); //传结构体
print2(&s); //传地址
return 0;
}
结果:
1000
1000
print1 和 print2 函数中,首选print2函数
结构体传参的时候,要传结构体的地址。
三种情况的函数调用:
- 调用input函数时,实参是指针变量p,形参是结构体数组,传递的是结构体元素的起始地址,函数无返回值。
- 调用max函数时,实参是指针变量p,形参时结构体数组,传递的是结构体元素的起始地址,函数的返回值是结构体类型数据。
- 调用print函数时,实参是结构体变量(结构体数组元素),形参是结构体变量,传递的是结构体变量中各成员的值,函数无返回值。