C语言结构体(struct)常见使用方法
了解和学会使用结构体有助于我们使用编程来对一个对象进行描述,以便解决生活中的问题。本篇博客主要介绍了结构体的大概内容,希望对大家有帮助。
C语言结构体(struct)常见使用方法
一. 什么是结构体
编程的一大意义是解决生活中的问题,而生活中的一些对象我们并不能单单通过C语言中的某一个变量类型来描述。比如一本书我们该如何用编程语言描述呢?一个整型变量?浮点型变量?肯定是不行的。所以C语言提供了结构体,由一系列具有相同类型或不同类型的数据构成的数据集合,是一种数据结构。描述一本书,我们得通过描述它的价格(浮点型变量),书名(字符串),作者(字符串),出版社(字符串)等等。
二. 结构体的声明与定义
2.1 一般情况
想要通过结构体来描述一本书,我们得学会结构体的定义与声明。
提供四种方式
第一种:
struct book
{
char name[20];
float price;
char author[20];
char publish[20];
};
第二种:
struct book
{
char name[20];
float price;
char author[20];
char publish[20];
} b1, b2, b3;//顺便定义了三个struct book类型的变量
注意如果struct book
如果定义在main函数外部时,b1,b2,b3都是全局变量。
第三种:
struct book
{
char name[20];
float price;
char author[20];
char publish[20];
};
int main()
{
struct book b1, b1, b3;
return 0;
}
第四种:只声明,不定义。
以下代码只是举例一个场景,变量名没有实际意义
struct book;
struct store
{
struct book n[20];
char name[20];
};
struct book
{
struct store a;
float price;
};
该场景就是两个结构体都需要用到对方,所以可以先声明一个结构体以免编译出错。
2.1 特殊的声明(匿名结构体)
//匿名结构体类型
struct
{
int a;
float b;
}x;
struct
{
int a;
float b;
}*p, n[20];
注意:这样写代码,编译器会将x与n当成两种不同的类型
三. 结构体的自引用
即结构体中包含一个类型为该结构体本身的成员。该怎么写呢?
//自引用
struct book
{
float price;
struct book next;
};
这样写可以吗?如果可以,那么sizeof(struct book)又是多少呢?答案是算不出来的。所以这样写有一定的问题。实际该这样写:
//自引用的正确写法
struct book
{
float price;
struct book* next;//写成指针
};
四. 结构体的初始化
第一种:
struct student
{
char name[20];
int age;
};
int main()
{
struct student s1 = { "zhangsan",20 };//定义时初始化
return 0;
}
第二种方法:
struct student
{
char name[20];
int age;
}s2 = { "lisi",16 };//结构体声明的同时定义变量并且初始化
第三种方法:
#include <stdio.h>
struct student
{
int id;
int age;
};
int main()
{
struct student s3 = { .age = 12,.id = 20 };//通过.操作符来选择先初始化哪个成员
printf("%d %d\n", s3.id, s3.age);
}
程序运行结果:
五. 结构体的使用
结构体的使用主要就是通过.操作符来访问成员。
#include <stdio.h>
#include <string.h>
struct book
{
float price;
char name[20];
};
int main()
{
struct book b1 = { 23.5f,"Cplus" };
printf("%.2f %s\n", b1.price, b1.name);
b1.price = 33.6f;
strcpy(b1.name, "haha");
printf("%.2f %s\n", b1.price, b1.name);
return 0;
}
对于结构体指针来说,可以通过->操作符来访问结构体成员。
#include <stdio.h>
#include <string.h>
struct book
{
float price;
char name[20];
};
int main()
{
struct book b1 = { 23.5f,"Cplus" };
struct book* sb1 = &b1;
printf("%.2f %s\n", sb1->price, sb1->name);//写法1
b1.price = 33.6f;
strcpy(b1.name, "haha");
printf("%.2f %s\n", (*sb1).price, (*sb1).name);//写法2
return 0;
}
六. 结构体的内存对齐
对于如何定义与使用结构体,我们已经大概了解了。现在又遇到了难题:如何计算结构体占用内存的大小?
6.1 内存对齐规则
- 第一个成员在与结构体变量偏移量为0的地址处。
- 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。 VS中默认的值为8
- 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
- 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整 体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
6.2 计算练习
#include <stdio.h>
int main()
{
struct S2
{
char c1;
int i;
char c2;
};
printf("%d\n", sizeof(struct S2));
return 0;
}
#include <stdio.h>
int main()
{
struct S2
{
char c1;
char c2;
int i;
};
printf("%d\n", sizeof(struct S2));
return 0;
}
内存分布大概就是这样
6.3 内存对其的意义
- 平台原因(移植原因): 不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特 定类型的数据,否则抛出硬件异常。
- 性能原因: 数据结构(尤其是栈)应该尽可能地在自然边界上对齐。 原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
总体来说:结构体的内存对齐是拿空间来换取时间的做法。
所以我们在声明结构体时,比较节约内存空间的方法是:让占用空间小的成员尽量集中在一起。
6.4 修改默认对其数
主要用到#pragma这个预处理指令
#include <stdio.h>
#pragma pack(8)//设置默认对齐数为8
struct S1
{
char c1;
int i;
char c2;
};
#pragma pack()//取消设置的默认对齐数,还原为默认
#pragma pack(1)//设置默认对齐数为1
struct S2
{
char c1;
int i;
char c2;
};
#pragma pack()//取消设置的默认对齐数,还原为默认
int main()
{
printf("%d\n", sizeof(struct S1));
printf("%d\n", sizeof(struct S2));
return 0;
}
程序运行结果:
七. 结构体传参
结构体传参主要以两种形式,结构体传参和结构体地址传参。
#include <stdio.h>
struct S
{
int count[20];
int num;
};
struct S s = { {1,2,3,4}, 20 };
//结构体传参
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;
}
程序运行结果:
可以看到两种方式得到的结果都是一样的。但是请想一想,如果结构体本身的成员就占用着很大的内存呢?(比如一个很大的数组)这时再使用结构体传参就会有很大的内存消耗。
结构体传参直接传结构体的话,内存消耗和时间消耗都会更大。
所以建议使用结构体指针传参。
总结
了解和学会使用结构体有助于我们使用编程来对一个对象进行描述,以便解决生活中的问题。
本篇博客主要介绍了结构体的大概内容,希望对大家有帮助。
结构体部分的难点是自主运用和结构体占用空间大小,建议多练点题来熟悉。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)