结构体
功能
- 为了让一组数据有联系
- 可以在函数内定义,也可以在函数外面,在外面可以多个函数引用
类型
类型说明符 成员名;
变量
⑴先定义类型,再定义变量
1 2 3 4 5 6 7 8
| struct stu { int mun; char name; char sex; float score; }; struct stu boy1,boy2;
|
⑵在定义类型的同时定义变量
1 2 3 4 5 6 7
| struct { int mun; char name; char sex; float score; }boy1,boy2;
|
⑶直接定义结构体变量
1 2 3 4 5 6 7
| struct stu { int mun; char name; char sex; float score; }boy1,boy2;
|
- 说明:
- 使用
typedef
更好定义,也更简洁
⑵
与⑶
的区别就是⑶
没有结构体名,直接是变量
- 一个结构体类型所占的字节并不是所有类型的字节加起来,(使用
sizeof(struct 结构体名)
可以查看)因为读取效率问题,所以编译器会默认数据对齐
- 结构体可以嵌套使用
- 结构体是用户定义的,不是唯一的
- 只有说明变量系统才会分配空间
- 结构体指针变量同样可以这样定义
指针
- 结构体和数组不一样,没有首地址这种说法,要想得到地址必须使用
&
结构体的初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| #include <stdio.h>
struct date { int month; int day; int year; };
int main(int argc, char const *argv[]) { struct date today = {11, 13, 2019}; struct date thismonth = {.month=11, .year=2019}; printf("%i-%i-%i\n", today.year, today.month, today.day); printf("%i-%i-%i\n", thismonth.year, thismonth.month, thismonth.day);
return 0; }
|
访问成员的运算符
1.成员运算符.
格式:结构体变量名.成员名
功能:访问结构体内的成员
2.指针运算符->
1 2 3 4 5 6 7
| struct str{ int num ; char name[ 20 ] ; char sex ; struct date birthday ; float score; }boy1,boy2,*ptr1;
|
1
| printf("%d", boy1.name);
|
可以输出boy1
的成员name
1
| printf("%d", ptr1->num);
|
- 说明
- 如果成员本身是一个结构体的话,则需要引用到具体的成员才行.
- 结构体必须被初始化才有意义
- 但我发现定义结构体成员后默认数据是
0
,指针是NULL
.
和->
的优先级比较高,仅次于()
结构体的对齐
- 数据类型自身的对齐值:对于
char
型数据,其自身对齐值为1
,对于short
型为2
,对于int,float,double
类型,其自身对齐值为4
,单位字节
- 结构体的自身对齐值:其成员中自身对齐值最大的那个值
- 指定对齐值:
#pragma pack (value)
时的指定对齐值value
- 数据成员和结构体的有效对齐值:数据成员(数据类型)和结构体的自身对齐值和指定对齐值中小的那个值。(数据成员对齐了数据结构自然也就对齐了)
说明:
- 有效对齐值N是最终采用的对齐方式,对齐N也就是说存放的原始地址%N=0.
- 数据结构中的变量都是按定义的先后顺序排放的,第一个数据的起始地址就是数据结构的初始地址.
- 结构体的变量占用的总长度必须是有效对齐值的整数倍.
例子
1 2 3 4 5 6 7 8 9 10 11
| #include<stdio.h>
main() { struct B{ char b; int a; short c; }; printf("%d",sizeof(struct B)); }
|
运行结果为12
解释:
int
自身对齐值是4
,只能存放0x0004
到0x0007
这四个字节,才能满足0x0004%4=0
short
自身对齐值2
,占0x0008
和0x0009
,所以0x0000
到0x0009
都是B
的内容
- 由于只有
10
个字节,结构体的有效对齐值是4
,因为编译器为了实现结构数据的存取效率,所以自动补充2
个字节满足(10+2)%4=0
结构体参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| #include <stdio.h>
struct date { int x; int y; };
struct date getStruct(void);
void putStruct(struct date);
int main(int argc, char const *argv[]) { struct date a={0, 0}; a = getStruct(); putStruct(a);
return 0; }
struct date getStruct(void){ struct date pg; scanf("%d", &pg.x); scanf("%d", &pg.y); return pg; }
void putStruct(struct date pp){ printf("x=%d,y=%d\n", pp.x, pp.y); }
|
指针型(推荐使用):
K & R:If a large structrue is to be passed to a function, it is generally more efficient to pass a pointer then to copy the whole structrue.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| #include "stdio.h"
struct date { int x; int y; };
struct date* getStruct(struct date*); void outputs(const struct date*); void output(struct date p);
int main(int argc, char const *argv[]) { struct date a={0, 0}; getStruct(&a); output(a); output(*getStruct(&a)); outputs(getStruct(&a));
return 0; }
struct date* getStruct(struct date *pa){ scanf("%d", &(*pa).x); scanf("%d", &pa->y); printf("pa->x=%d,pa->y=%d\n", pa->x, pa->y); return pa; }
void outputs(const struct date* outpa){ printf("outpa->x=%d,outpa->y=%d\n", outpa->x, outpa->y); }
void output(struct date p){ printf("p.x=%d,p.y=%d\n", p.x, p.y); }
|
结构的嵌套
结构数组
1 2 3 4 5 6 7 8 9 10 11 12 13
| struct time { int hour; int minute; int seconds; } struct time testTime[5] = { {01,33,11}, .... }
|
结构中的结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #include <stdio.h>
struct point{ int x; int y; };
struct rectangle{ struct point p1; struct point p2; };
int main(){ struct rectangle r, *rp; rp = &r; r = (struct rectangle){{1,2}, {3,4}};
printf("%d\n", ((rp->p1.x)+1)); printf("%d\n", (rp->p2.x)); return 0; }
|
结构中的结构的数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| #include <stdio.h>
struct point{ int x; int y; };
struct rectangle{ struct point p1; struct point p2; };
int main(int argc, char const *argv[]) { int i; struct rectangle rects[] = { { {1,2}, {3,4} },{ {5,6}, {7,8} } };
return 0; }
|