结构体
- 结构体
- 结构体中元素的类型可以不一样,且只能包含元素,没有函数,称之为成员
- 所有成员变量内存地址连续,符合字节对齐规则
- 创建的结构体相当于一个新的类型
数组和结构体
数组 | 结构体 | |
---|---|---|
存储的数据类型 | 数据类型一致 | 数据类型可以不一致 |
访问方式 | 通过下标或指针移动相应的数据类型大小 | |
储存地址方式及规则 | 地址连续 | 地址连续但遵循字节对齐 |
struct name struct man
{ {
数据类型 成员; char name[20];
}; };
struct node no; //错误,n是一个变量类型,没有实际数据类型
访问方式
.
: 结构体变量->
:指针变量,非指针类型不可使用
struct node
{
int x;
char c;
};
int main()
{
struct node no;
no.c = 'a';
no.x = 10;
printf("%c %d",no.c,no.x);
return 0;
}
struct node
{
int x;
char c;
}no = {10,'a'},n1={20,'b'}; //全局变量
int main()
{
printf("%c %d",no.c,no.x); //一样
printf("%c %d",n1.c,n1.x); //一样
return 0;
}
typedef struct node //此处的node可以省略
{
int x;
char c[255];
}NODE; //加上typedef后node是类型名
int main()
{
NODE no; //此时不用写struct
//struct node no == NODE no
strcpy(no.c,"ssss");
no.x = 10;
printf("%s %d",no.c,no.x);
return 0;
}
- 结构体在未使用时,不会开辟内存空间,在声明一个结构体变量后会按照字节排序分配空间
struct node
{
int x;
char c;
int *p;
};
int main()
{
struct node no;
char ch = 'a';
no.p = (int *) malloc (sizeof(int) * 8);
for(int i=0;i<=8;i++)
*(no.p + i) = i;
for(int i=0;i<=8;i++)
printf("%d",*(no.p + i));
free(no.p);
no.p = NULL;
return 0;
}
- 如果是结构体指针变量,先开辟内存,指向有效内存,再这个基础上申请成员的内存;结束时先释放成员,再释放节点
typedef struct
{
char c;
int *p;
}node;
int main()
{
node* no = NULL;
no = (node*) malloc (sizeof(node));
if(no == NULL)
return -1;
no->p = (int*) malloc (sizeof(int) * 22);
if(no->p == NULL)
{
free(no->p); //把申请过的放掉
no -> p = NULL;
return -1;
}
if(no -> p != NULL)
{
free(no->p); //先释放成员的内存
no -> p = NULL;
}
if(no -> p != NULL)
{
free(no); //在释放节点内存
no = NULL;
}
return 0;
}
结构体空间
- 空结构体占 0 字节
- 结构体指针变量占指针字节
字节对齐
- 结构体地址大小是最大成员类型的整数倍
- 小类型占位 = 相近大类型占位
- 已经对齐的元素看成整体,与后一个对齐
typedef struct
{
char
double
int
char
}stu;
int main()
{
stu man;
printf("%d\n",sizeof(man));
return 0;
}
#pragma pack(n) //设定变量以n字节对齐,、
//n为8时,char类型不变
//n越小,节省空间
#pragma pack(2)
typedef struct
{
char
int
char
}stu;
//大小为8
位域
- 将多个位域成员存储在同一个类型内存中
- 位域取值不能超过位数的最大值
- 位域用于
unsigned
整数数据类型,浮点数不行
typedef struct
{
char a : 5; //只用5比特位
double b : 3; //不能超过 0b111
int c : 4;
char d : 7;
}stu;
int main()
{
stu man;
printf("%d\n",sizeof(man));
return 0;
}
与结构体的区别
- 所占大小不一样
- 取值范围
- 结构体大小取值依赖数据类型
- 位域仅通过字节数取值范围
- 位域不能使用
&
共用体
union
: 所有成员共用一段内存,同时刻只有一个成员有效,这个空间的值只能是最新的一个赋值- 内存大小:最大成员所占内存,遵循内存对齐,
- 如果结构体套联合体,内存是整个结构体的最大类型的整数倍
union name
{
int a;
double d;
char str[17];
}; //size = 8
int main()
{
union name na;
sizeof(na); //17 -> double(8) -> 24
na.d = 2.1;
na.a = 10;
na.c = 'a';
printf("%d,%c",na.a,na.c); //97,a
}
//float 因为存储方式不一样,输出可能不对
枚举
- 枚举存放的数据是整数常量,可以重复,
enum name
{
data0;
data1;
data2;
datan;
};
- 枚举常量默认从0开始依次递增
- 可以手动指定枚举常量的值,未指定则在前一个基础上加一
- 不能引出枚举体中的量,只能被赋值
enum weekday
{
MON = 1,TUE,WED,THU,FRI,SAT,SUN
};