AutoLeaders控制组—C语言结构体学习笔记
一.结构体简介
设计程序时,最重要的步骤之一是选择表示数据的方法。在许多情况下,用简单变量甚至是数组来表示数据还不够。这时我们就需要用到结构体来提高你表示数据的能力。
二.声明结构体
声明结构体, 描述了一个结构的组织布局。声明类似下面这样:
#include <stdio.h>
int main(){
struct date {
int month;
int day;
int year;
};
return 0;
}
1.关键字
首先是关键字struct,它表明跟在其后的是一个结构,后面是一个可选的标记(该例中是date),稍后程序中可以使用该标记引用该结构。
2.结构体成员列表
在结构体声明中,用一对花括号括起来的是结构成员列表。每个成员都用自己的声明来描述。此例,含有int型的month,day,year成员可以是任意一种C的数据类型,甚至可以是其他结构!
3.分号
右花括号后面的分号是声明所必需的,表示结构布局定义结束。
4.结构体的位置
和本地变量一样,可以把结构体声明放在所有函数的外部,也可以放在一个函数定义的内部(如本例所示)。
如果把结构体声明置于一个函数的内部,它的标记就只限于该函数内部使用。如果把结构体声明置于函数的外部,那么该声明之后的所有函数都能使用它的标记
#include <stdio.h>
struct date {
int month;
int day;
int year;
};
int main(int argc, char const *argv[]){
struct date today;
today.month = 07;
today.day = 31;
today.year = 2014;
printf("Today's date is %i-%i-%i.\n", today.year,today.month,today.day);
return 0;
}
所以通常在函数外部声明结构体类型,这样就可以被多个函数所使用
5.声明结构体的形式
声明结构体有多种方式,下列三种皆可行:
struct point{ //第一种
int x;
int y;
};
struct point p1,p2;
//pl和p2都是point,里面有x和y的值
struct{ //第二种
int x;
int y;
} p1,p2;
//p1和p2都是一种无名结构,里面有x和y
struct point { //第三种
int x;
int y;
} p1, p2;
//pl和p2都是point,里面有x和y的值
对于第一和第三种形式,都声明了结构point。但是第二种形式没有声明point,只是定义了两个变量
三.结构变量
1.定义结构变量
运用结构体之前我们需要声明结构类型,在声明之后我们则需要定义结构变量
如下:
#include <stdio.h>
struct date {
int month;
int day;
int year;
};
int main(int argc, char const *argv[]){
struct date today; //定义结构变量
return 0;
}
这样我们就定义了结构变量today
2.结构的初始化
结构变量的初始化与数组初始化类似
第一种:用大括号直接对所有变量赋值。
第二种:具体指明某种变量的值,未被指明的变量则初始化为0
struct date {
int month;
int day;
int year;
};
struct date today={ 32,520,1314}; //第一种
struct date tomorrow ={.month=7,.year=520};//第二种
3.结构成员
结构和数组类似,但结构中的变量可以不同
数组用[ ]运算符和下标访问其成员如: a[0]= 10;
结构用 . 运算符和名字访问其成员如:
struct date {
int month;
};
struct date today;
today.month;
4.结构运算
若要访问整个结构,可以直接用结构变量的名字
对于整个结构,可以做赋值、取地址,也可以传递给函数参数
例如:
p1 = (struct point){5,10}; // 相当于p1.x=5; p1.y=10;
p1 = p2; //相当于p1.x = p2.x;p1.y= p2.y;
5.结构指针
结构变量的名字并不是结构变量的地址,因此在访问其地址是必须使用&运算符 如:
struct date *pDate=&today;
表示指向结构的指针pDate取today的地址
四. 结构与函数
1.作为函数参数
结构体可以作为函数参数传入函数中
如:
int number (struct date d);
struct date today;
number(today);
结构变量today作为参数传入函数number中
这时候是在函数内新建一个结构变量,并复制调用者的结构的值
2.输入结构
结构作为函数参数,传递进入函数是值的传递,而不是整个结构传入进函数。
有代码验证:
#include <stdio.h>
struct point {
int x;
int y;
};
void getStruct(struct point);
void output(struct point);
int main (int argc, char const *argv[ ])
{
struct point y = {0,0};
getStruct(y);
output(y);
}
void getStruct (struct point p)
{
scanf("%d", &p.x);
scanf("%d",&p.y);
printf("%d, %d", p.x,p.y);
}
void output(struct point p)
{
printf("%d,%d", p.x,p.y);
}
此代码证明了传入函数getStruct中的结构变量y与结构变量p毫无联系,只是把变量y的值传入进了函数
若要创造一个函数(输入结构变量的值并把结构变量带回来),可以在输入函数中完全创建一个临时的结构变量,然后把这个结构返回给调用者
利用的是结构可以互相进行赋值
只需在上述代码中稍作修改:
#include <stdio.h>
struct point {
int x;
int y;
};
struct point getStruct(void); //定义函数
void output(struct point);
int main (int argc, char const *argv[ ])
{
struct point y = {0,0};
y=getStruct(); //用结构函数getStruct()对结构y进行赋值
output(y);
}
struct point getStruct (void)
{
struct point p;
scanf("%d", &p.x);
scanf("%d",&p.y);
printf("%d, %d", p.x,p.y);
return p; //将结构变量p的值带回去
}
void output(struct point p)
{
printf("%d,%d", p.x,p.y);
}
但此做法不如用结构指针作为参数
我们可以用指向结构的指针对结构变量进行修改
例如:
struct date {
int month;
int day;
int year;
} myday;
struct date *p = &myday;
p->month = 12;
此代码,用指针p对结构变量myday中的成员month进行了修改
用->表示指针所指的结构变量中的成员,->是一个运算符,它的左边必须是指向结构的指针
五. 结构数组
1声明结构数组
声明结构数组和声明其他类型的数组类似。下面是一个声明结构数组的例子:
struct date dates [100];
以上代码把dates声明为一个内含100个元素的数组。数组的每个元素都是一个date类型的结构。因此,dates[0]是第1个date类型的结构变量,dates[1]是第2个date类型的结构变量,以此类推。数组名dates本身不是结构名,它是一个数组名,该数组中的每个元素都是struct date类型的结构变量。
2. 初始化结构数组
初始化结构数组需要两层大括号,最外侧大括号是对数组进行初始化,里面每一层大括号是对dates[ ]进行赋值
例如:
struct date dates []={
{4,5,2005},{2,3,1314}};
六.嵌套结构
有时,在一个结构中包含另一个结构即(嵌套结构)很方便
struct point {
int x;
int y;
};
struct rectangle {
struct point pt1;
struct point pt2;
};
struct rectangle r;
如果有变量 struct rectangle r;
就可以有: r.pt1.x 、 r.pt1.y 、 r.pt2.x 、r.pt2.y
r和pt1、pt2都是结构,若用指针来调取r的地址
变量定义:
struct rectangle r, *rp;
rp=&r;
那么下面的四种形式是等价的:
r.pt1.x
rp->pt1.x
(r.pt1).x
(rp->pt1).x
都表示指向结构变量r中的结构变量pt1中的变量x
但是没有rp->pt1->x(因为ptl不是指针)