C语言结构体详解(声明,使用,优化)

结构体声明的方法

结构体声明最常见的有四种方法。
1.直接定义结构体变量。
2.声明结构体的同时定义结构体变量。
3.先声明结构体再定义变量。
4.用typedef 重定义。

1.直接定义结构体变量

struct
{
   char       str1[10];
   char       str2[10];
   short      str3[10];
   int        str4[10];
   float      str5[10];
   double     str6[10];
   long       str7[10];
   long long  str8[10];
}Variable_name1, Variable_name2;

这种方法比较死板,如果需要再添加几个相同类型的结构体就没有办法添加了。一般不建议使用,除非你确定只需要Variable_name1, Variable_name2。而不会添加新结构体Variable_name3, Variable_name4。

2.声明结构体的同时定义结构体变量

struct statement
{
   char       str1[10];
   char       str2[10];
   short      str3[10];
   int        str4[10];
   float      str5[10];
   double     str6[10];
   long       str7[10];
   long long  str8[10];
}Variable_name1, Variable_name2;

Variable_name1和Variable_name2已经是结构体变量了,如果需要添加新的结构体变量

struct statement  Variable_name3, Variable_name4;

这样定义看起来不整洁,而且初学者可能搞不清楚 statement 和 Variable_name1, Variable_name2的区别是什么,或者不清楚二者怎么去用,所以不建议初学者这样用。

3.先声明结构体再定义变量

struct statement
{
   char       str1[10];
   char       str2[10];
   short      str3[10];
   int        str4[10];
   float      str5[10];
   double     str6[10];
   long       str7[10];
   long long  str8[10];
};



struct statement  Variable_name1, Variable_name2;
struct statement  Variable_name3, Variable_name4;

这样初学者看起来会比较容易理解,statement是结构体,不能直接使用,只能用来定义结构体变量,定义之后的结构体变量才可使用。

4.用 typedef 重定义结构体

typedef struct 
{
   char       str1[10];
   char       str2[10];
   short      str3[10];
   int        str4[10];
   float      str5[10];
   double     str6[10];
   long       str7[10];
   long long  str8[10];
}statement;



statement  Variable_name1, Variable_name2;
statement  Variable_name3, Variable_name4;

用 typedef 重定义结构体名为 statement,定义结构体变量时直接 statement 后面跟结构体变量名就行,跟第三种方法比起来定义结构体变量时少了 struct 这个关键字,是最简单也是最简洁的方法,本人就喜欢这种方法,看每个人的习惯不一样,可以根据自己的习惯来使用适合自己的方法

注意:typedef 的作用是为一种类型引入新的名字,而不是为变量分配空间。在某些方面,typedef 类似于宏文本替换——它并没有引入新的类型,而是为现有的类型取一个新的名字。uint32_t,uint8_t 等都是通过 typedef 把数据类型重定义得来的新名字。

结构体字节对齐特点

以前我一直以为结构体是四字节对齐的,直到后面使用遇到问题我才知道,结构体是以结构体成员里面占内存最大的对齐方式来对齐,比如结构体成员里面最大变量占一个字节,该结构体就以一字节对齐方式对齐,结构体成员里面最大变量占两个字节,该结构体就以两字节对齐方式对齐,结构体成员里面最大变量占八个字节,该结构体就以八字节对齐方式对齐。

这样对齐的原因是因为:结构体的最终大小必须是其成员(基础数据类型成员)里最大成员所占字节的整数倍

要验证结构体对齐方式,我们首先要知道编译器里各种数据类型所占的大小,因为不同编译器中同一数据类型所占字节数是不一样的,比如 int 可以是两个字节,也可以是四个字节,double 可以是占四个字节,也可以是占八个字节。我们来看看几种常用数据类型所占字节大小。

typedef struct 
{
  char       a;
  short      b;
  char       c;
  char       d;
}statement1;


statement1  Variable_name1;

在这里插入图片描述
按前面所说,该结构体最大成员占两个字节,所以为两字节对齐,所 a =2 , b =2, c+d =2, 所以一共占六个字节。

typedef struct 
{
  double     a;
  char       b;
  short      c;
  int        d;
  int        e;
  char       f;
  float      g;
}statement1;


statement1  Variable_name1;

我们来分析一下这个结构体占几个字节
该结构体里面的成员最大占八个字节,所以是八字节对齐方式,a =8, b+c+d =8, e+f =8 float =8, 所以该结构体所占大小为32 字节,下面我们来运行一下看结果对不对

结果是对的

注意:相同成员的结构体因为放置成员的顺序不同,可能会导致结构体所占空间大小不同,所以在使用时要尽量合理放置顺序,避免造成不必要的内存资源浪费

结构体优化

我们在做项目过程中,经常会用到很多标志位,只需要一位(即0和1)就行,对于51单片机来说,可以用bit ,但是对于32单片机来说最小的数据类型都是八位,如果标志位很多的时候,就会造成大量的内存资源浪费,毕竟内存大的单片机价格会高很多,所以需要做一些内存优化,比如结构体和枚举全部放共用体里面,就算如此,结构体如果不优化,所占内存还是结构体大小,并没有对实质的内存进行优化。只是节省了少部分枚举所占内存,大量内存还是结构体浪费了。

这就引入一个经常和结构体一起使用的东西,位域。位域配合结构体使用起来就比较灵活,而且不会浪费资源,需要多少位就用多少位。

typedef struct 
{
  char a     :1;
  char b     :1;
  char c     :1;
  char d     :1;
  char e     :1;
  char f     :1;
  char g     :1;
  char h     :1;
}statement1;

statement1  Variable_name1;


所占大小为一个字节,如果是八个char 类型那就得占八个字节,内存得到了很大的优化。

typedef struct 
{
  char a     :3;
  char b     :1;
  char c     :1;
  char d     :1;
  char e     :1;
  char f     :1;
  char g     :1;
  char h     :1;
}statement1;

statement1  Variable_name1;


在使用位域时也要注意,不足一个字节的剩余部分也会占一个字节。所以使用时合理放置顺序。

typedef struct 
{
  char a        :1;
  char b        :1;
  char c        :1;
  char d        :1;
  char e        :1;
  char f        :1;
  char g        :1;
  short  h      :1;
}statement1;


statement1  Variable_name1;

typedef struct 
{
  char a        :1;
  char b        :1;
  char c        :1;
  char d        :1;
  char e        :1;
  char f        :1;
  char g        :1;
  int  h        :1;
}statement1;


statement1  Variable_name1;

typedef struct 
{
  char a        :1;
  char b        :1;
  char c        :1;
  char d        :1;
  char e        :1;
  char f        :1;
  char g        :1;
  int  h        :25;
}statement1;


statement1  Variable_name1;

typedef struct 
{
  char a        :1;
  char b        :1;
  char c        :1;
  char d        :1;
  char e        :1;
  char f        :1;
  char g        :1;
  int  h        :26;
}statement1;


statement1  Variable_name1;

位域也是跟据数据类型来进行字节对齐的,也是按成员里面最大的成员所占字节数来对齐,数据类型都是char类型就是以一字节对齐,不足和超过的部分都按一字节,例如6位占一个字节,9位就是占两个字节(8+1占两个 一字节)。成员最大为 short 就以两字节对齐,整个结构体所占不足或者超过16位,也是按两字节对齐,例如,10位占两字节,17位占四字节(16+1就是两个两字节)。最大成员为 int 就以四字节对齐,不足和超过的部分都是以四字节对齐,例如 ,3位是占四字节 ,33位则占八字节(32+1 就是两个四字节)。

注意;float 和 double 不能使用位域。

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用\[1\]:C语言字节对齐问题详解中提到了C语言中的字节对齐问题。在结构体中,为了提高内存访问的效率,编译器会对结构体进行字节对齐。这意味着结构体的成员在内存中并不是紧凑排列的,而是按照一定的规则进行对齐。具体的对齐规则取决于编译器和编译选项。\[1\] 引用\[2\]:在C语言中,可以使用宏offsetof来获取结构体成员相对于结构体开头的字节偏移量。这个宏非常有用,可以帮助我们计算出每个结构体成员相对于结构体开头的偏移字节数。通过这个宏,我们可以更好地理解结构体的内存布局。\[2\] 引用\[3\]:在C语言中,指针和结构体的组合常常用于处理复杂的数据结构。指针可以指向结构体的成员,通过指针可以方便地对结构体进行操作。指针和结构体的组合可以实现更灵活的数据处理和内存管理。\[3\] 综上所述,C语言中的指针结构体组合可以用于处理复杂的数据结构,而字节对齐问题则是在结构体中为了提高内存访问效率而进行的优化。通过使用宏offsetof,我们可以更好地理解结构体的内存布局。 #### 引用[.reference_title] - *1* *3* [结构体指针,C语言结构体指针详解](https://blog.csdn.net/weixin_34069265/article/details/117110735)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [C语言结构体详解](https://blog.csdn.net/m0_70749276/article/details/127061692)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值