结构体的定义
struct 结构体名
{
结构体成员列表
};
struct student
{
int num;
char name[16];
float score;
};
结构体的使用
struct 结构体名 变量名;
struct 结构体名 变量名 = {
成员1,
成员2,
…
};
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
struct stu {
char name[16];
int age;
float score;
};
int main() {
//赋值方式一
struct stu s;
strcpy(s.name, "zs");
s.age = 18;
s.score = 60;
printf("name = %s,age = %d,score = %.1f\n", s.name, s.age, s.score);
赋值方式二
struct stu s2 = { "ls",18,78 };
printf("name = %s,age = %d,score = %.1f\n", s2.name, s2.age, s2.score);
return 0;
}
结构体数组
定义:
struct 结构体名
{
结构体成员列表
}变量名[N];
或者在使用时:
struct 结构体名 变量名[N];
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
struct stu
{
char name[16];
int age;
float score;
} s[3];
int main()
{
struct stu* p = &s;
strcpy(p->name, "zs");
p->age = 18;
p->score = 60.5;
p++;
strcpy(p->name, "ls");
p->age = 20;
p->score = 78;
p++;
strcpy(p->name, "ww");
p->age = 19;
p->score = 90.0;
p = &s;
int i;
for (i = 0; i < sizeof(s) / sizeof(struct stu); i++)
{
printf("name = %s,age = %d,score = %.1f\n", p->name, p->age, p->score);
p++;
}
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
//定义结构体
struct student
{
int num;
char name[16];
float score;
};
int main()
{
struct student stu[3] = { {1000, "zs", 99}, {1001, "lisi", 89}, {1003, "ww", 79} };//赋值方式一
struct student stu1[3];
//赋值方式二
stu1[0].num = 2000;
strcpy(stu1[0].name, "lh");
stu1[0].score = 100;
printf("num = %d, name = %s, score = %f\n", stu1[0].num, stu1[0].name, stu1[0].score);
int i;
for (i = 0; i < 3; i++)
{
printf("num = %d, name = %s, score = %f\n", stu[i].num, stu[i].name, stu[i].score);
}
return 0;
}
结构体指针
使用:
struct 结构体名 * 变量 = &变量名(结构体);
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
//定义结构体
struct student
{
int num;
char name[16];
float score;
};
int main()
{
struct student stu;
struct student* p = &stu;
/*
* 通过结构体变量去赋值
stu.num = 1000;
strcpy(stu.name, "lisi");
stu.score = 90;
*/
//通过结构体指针去赋值
p->num = 1000;
strcpy(p->name, "lisi");
p->score = 90;
printf("num = %d, name = %s, score = %f\n", stu.num, p->name, p->score);
return 0;
}
结构体嵌套
定义:
struct 结构体名{
struct 结构体名 成员名;
};
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
struct person
{
char name[16];
int age;
char sex;
};
struct student
{
struct person stu;
float score;
};
struct teacher
{
struct person tea;
char phone[12];
};
int main()
{
struct student s;
strcpy(s.stu.name, "zhangsan");
s.stu.age = 12;
s.stu.sex = 'm';
s.score = 98;
printf("name = %s,age = %d, sex = %c, score = %f\n", s.stu.name, s.stu.age, s.stu.sex, s.score);
struct teacher t;
struct teacher* p = &t;
strcpy(p->tea.name, "lisi");
p->tea.age = 54;
p->tea.sex = 'w';
strcpy(p->phone, "18674074000");
printf("name = %s,age = %d, sex = %c, score = %s\n", t.tea.name, t.tea.age, t.tea.sex, t.phone);
return 0;
}
结构体大小
结构体的大小计算遵循结构体的对齐规则:
- 第一个成员在与结构体变量偏移量为0的地址处。(即结构体的首地址处,即对齐到0处)
- 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
- 结构体的总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
- 如果嵌套了结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
- 对齐数 = 该结构体成员变量自身的大小与编译器默认的一个对齐数的较小值。
注:VS中的默认对齐数为8,不是所有编译器都有默认对齐数,当编译器没有默认对齐数的时候,成员变量的大小就是该成员的对齐数。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
struct A
{
char a;
int b;
char c;
char d;
};
struct B
{
char a;
short b;
char c;
char d;
};
struct C
{
char a;
double b;
char c;
char d;
};
struct D {
char a;
double b;
struct C c;
char d;
char e;
};
int main()
{
printf("int = %d, %d\n", sizeof(int), sizeof(struct A)); //1,4,1,1 -> 4,4,4
printf("short = %d, %d\n", sizeof(short), sizeof(struct B));//1,2,1,1 -> 2,2,2
printf("double = %d, %d\n", sizeof(double), sizeof(struct C));//1,8,1,1 -> 8,8,8
printf("struct C = %d, %d\n", sizeof(struct C), sizeof(struct D));//1,8,24,1,1 -> 8,8,24,8
/*
int = 4, 12
short = 2, 6
double = 8, 24
struct C = 24, 48
*/
return 0;
}
位域
定义:
所谓的“位域”是把一个字节中的二进制位分为几个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。这样就可以把几个不同的对象用一个字节的二进制位域来表示。
struct 位域结构体名
{
位域列表;
};
其中位域列表的形式为:
类型说明符 位域名:位域长度;
位域变量说明:
struct 位域结构体名 变量名;
struct 位域结构体名 变量名 = {值1,值2…};
定义位域结构体时定义变量;
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
struct s1 {
unsigned int a : 8;
unsigned int b : 16;
unsigned int c : 8;
};
struct s2 {
unsigned char a : 1;
unsigned char b : 8;//不能超过8
unsigned char c : 5;
};
int main() {
printf("%d\n", sizeof(struct s1));//4 ,8+16+8 <32 所有占4个字节
printf("%d\n", sizeof(struct s2));//3 ,8+8+8
return 0;
}
位域的位数赋值:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
struct data_t {
unsigned int value : 34;//编译器不允许
unsigned int value : 0;//编译器不允许
};
int main() {
struct data_t data;
data.value = 10;
printf("value = %d", data.value);
return 0;
}
位域对齐:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
struct data_t1 {
unsigned char flag1 : 1;
unsigned int flag2 : 16;
unsigned char flag3 : 1;
};
struct data_t2 {
unsigned char flag1 : 1;
unsigned int flag2 : 16;
unsigned int flag3 : 1;
};
int main() {
printf("size : %d\r\n", sizeof(struct data_t1));//Windows下 = 12,Linux下 = 4
printf("size : %d\r\n", sizeof(struct data_t2));//Windows下 =8,Linux下 = 4
//字节对齐规则(编译器),编译器可能会在flag2前后插入填充字节以满足对齐要求
return 0;
}
位域的位级别操作:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
union data_u
{
struct {
unsigned char flag1 : 1;
unsigned char flag2 : 1;
unsigned char flag3 : 1;
unsigned char flag4 : 1;
}bits;
unsigned char byte;
};
int main() {
union data_u data;
data.bits.flag1 = 1;
data.bits.flag2 = 0;
data.bits.flag3 = 1;
data.bits.flag4 = 1;
printf("byte : %d\r\n", data.byte);//13
printf("bits size : %d\r\n", sizeof(data.bits));//1
return 0;
}