结构体的见解

本文详细介绍了C语言中的结构体,包括结构体的定义、有序与无序赋值方式、如何在结构体中使用其他结构体和指针,以及结构体大小的计算原则。同时,文章还探讨了结构体的位段概念,解释了位段的内存分配和使用注意事项,强调位段的非跨平台性。通过对实例的解析,帮助读者深入理解结构体的运用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是结构体

是由一批数据组合而成的结构型数据。组成结构型数据的每个数据称为结构型数据的“成员”。结构体类型不是由系统定义好的,而是需要程序设计者自己定义的。

结构体定义

struct为结构体关键字,student为结构体的标志,member-list为结构体成员列表,其必须列出其所有成员;variable-list为此结构体声明的变量。
例如

//struct student
{
      member-list
 } variable-list ; 

通常,student、member-list、variable-list这3部分至少要出现2个。
结构体的成员可以包含其他结构体,也可以包含指向自己结构体类型的指针,而通常这种指针的应用是为了实现一些更高级的数据结构如链表和树等。

结构体怎么赋值

有序赋值

只能进行一次,且再次进行就意味着重复定义

struct Init id2 = {1,1.1,"hello"};

无序赋值

这种方式利用成员运算符,进行赋值。而这种也是分为结构体内部赋值和结构体外部赋值

struct Init id2;
id2.a = 1;
id2.c = "world";
id2.d = 1.1;

struct Init id2 = {
	id2.a = -1,
	.c = "hello",
	.b = 4.0
};

结构体怎么使用

此结构体的声明包含了其他的结构体

struct COMPLEX{
    char string[100];
    struct SIMPLE a;
}; 

此结构体的声明包含了指向自己类型的指针

struct NODE{
    char string[100];
    struct NODE *next_node;
};

如果两个结构体互相包含,则需要对其中一个结构体进行不完整声明

struct B;    
//对结构体B进行不完整声明 
//结构体A中包含指向结构体B的指针
struct A{
    struct B *partner;
    //other members;
}; 
//结构体B中包含指向结构体A的指针,在A声明完后,B也随之进行声明
struct B{
    struct A *partner;
    //other members;
};

结构体的指针用法

typedef struct
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
} book_def;
book_def *pbook;
book_def book;

结构体的大小

上面说到,结构体的成员可以是不同类型的,各成员按照定义时的顺序依次存储在连续的内存空间。
那么,结构体的大小应该怎么计算呢。

计算原则

1.结构体变量的首地址,必须是结构体 “最宽基本类型成员” 大小的整数倍
2.结构体每个成员相对于结构体首地址的偏移量,都是该成员的整数倍。
3.结构体的总大小,为结构体 “最宽基本类型成员” (将嵌套结构体里的基本类型也算上,得出的最宽基本类型) 大小的整数倍。

例子

struct s1
{
char ch1;
int i;
char ch2;
};

ch1偏移量是0,i的偏移量不可能是1,因为偏移量要是i大小为4的倍数,所以i的偏移量是4,ch2的偏移量就变为了8,加ch2是9,要满足结构体大小是成员大小的整数倍,这个结构体的大小就是12。

struct s2
{
char ch;
int i;
char str[10];
};

前两个成员,大小是8,这个char类型的数组,只需要把它看做十个char连在一起即可,加起来就是18,再满足结构体大小为成员整数倍,所以大小就是20。

struct s3
{
char ch;
int i;
union
{
    char ch1;
    int j;
};
};

联合体大小就是成员中最大类型的大小,所以这个结构体大小是12.

结构体的位段

什么是结构体的位段

在一个结构体中以位为单位来指定其成员所占内存长度,这种以位为单位的成员称为“位段”或称“ 位域 ” 。

位段的内存分配

  1. 位段的成员可以是 int unsigned int signed int 或者是 char (属于整形家族)类型。
  2. 位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的。
  3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。
  4. 不建议int和char混用。

位段的使用

使用位段的时候要注意分配的内存是否足够,否则会发生截断。
例如:

#include <stdio.h>
int main()
{
   struct bs
   {
   	unsigned x : 2;
   	unsigned y : 4;
   	unsigned z : 7;
   } bit, * pbit;

   bit.x = 1;
   bit.y = 7;
   bit.z = 15;

   printf("%d,%d,%d\n", bit.x, bit.y, bit.z);

   pbit = &bit;
   pbit->x = 0;
   pbit->y &= 3;
   pbit->z |= 1;

   printf("%d,%d,%d\n", pbit->x, pbit->y, pbit->z);
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值