c语言结构体与共用体

目录

一、结构体

1、定义

2、常用用法

3、访问结构体成员

4、结构体大小计算

二、共用体

1、定义

2、作用

3、共用体大小计算


一、结构体

1、定义

结构体定义由关键字 struct 和结构体名组成,结构体名可以根据需要自行定义。

struct 语句定义了一个包含多个成员的新的数据类型,struct 语句的格式如下:

struct tag {
  member-list
  member-list
  member-list  
  ...
} variable-list ;

tag 是结构体标签。

member-list 是标准的变量定义,比如 int i; 或者其他有效的变量定义。

variable-list 结构变量,定义在结构的末尾,最后一个分号之前,可以指定一个或多个结构变量。

一般情况下,tag、member-list、variable-list 这 3 部分至少要出现 2 个。

举例:

struct Books
{
  char title[50];
  char author[50];
  char subject[100];
  int  book_id;
} book; //声明方式1

//声明方式2
struct Books book1;

通常使用typedef创建新类型

typedef struct 
{
  char title[50];
  char author[50];
  char subject[100];
  int  book_id;
} Books; 
//现在可以用Books作为类型声明新的结构体变量(代码更简洁)
Books book, books[50],*book1;

2、常用用法

结构体的成员可以包含其他结构体,也可以包含指向自己结构体类型的指针,而通常这种指针的应用是为了实现一些更高级的数据结构如链表和树等。

//此结构体的声明包含了其他的结构体
struct COMPLEX
{
  char string[100];
  struct SIMPLE a;
};

//此结构体的声明包含了指向自己类型的指针
struct NODE
{
  char string[100];
  struct NODE *next_node;
};

3、访问结构体成员

Books book = {"C 语言", "RUNOOB", "编程语言", 123456};//初始化
printf("title:%s", book.title);//访问结构体成员

指针访问结构体成员,语法为 pointer->member,等价于 (*pointer).member。

Books *book;
strcpy(book->title, "白夜行");

4、结构体大小计算

基本数据类型所占字节数:

结构体字节对齐:所占总内存为其成员变量中所占空间最大数据类型的整数倍。(划重点,数据类型)

struct example {
    char a;       // 1 byte
    int b;        // 4 bytes
    double c;     // 8 bytes
    short d;      // 2 bytes
};
//内存计算:

|1 + 3 |
|4     |
-->
|1 + 3 ||4     |
|8             |
|2 + 6         |
=
24

若包含数组:

#include <stdio.h>

struct Person {
    char name[20];
    int age;
    float height;
};

int main() {
    struct Person person;
    printf("结构体 Person 大小为: %zu 字节\n", sizeof(person));//28字节
    return 0;
}

对齐数与变量的类型和默认对齐数有关,VS编译其中默认的对齐数是8。

char name[20]的对齐数是默认对齐数8和char类型对应的1字节中较小的一个,即1。

float类型对应4字节。

最大成员(20)是最大对齐数(4)的整数倍,因此该结构体大小为4*5 + 4 + 4 = 28。


对齐原因

(1)平台原因:适应某些硬件平台,某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常;

(2)性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。(空间换取时间)

总结:所占内存小的成员放前面

二、共用体

1、定义

共用体是一种特殊的数据类型,允许在相同的内存位置存储不同的数据类型,但是同一时间只能使用一个成员变量。

举例如下:

union Data
{
    int i;
    float f;
    char  str[20];
};

int main( )
{
    union Data data;        

    data.i = 10;
    data.f = 220.5;
    strcpy( data.str, "C Programming");

    printf( "data.i : %d\n", data.i);
    printf( "data.f : %f\n", data.f);
    printf( "data.str : %s\n", data.str);
    //最终只有data.str正常输出,其他成员的值被损坏

    return 0;
}

2、作用

节省内存,常用于通信中的数据包,根据所收数据包的格式取出数据。

3、共用体大小计算

共用体的大小至少为最大成员的大小。

规则:

对齐数与变量的类型和默认对齐数有关,VS编译其中默认的对齐数是8。

char str[9]的对齐数是默认对齐数8和char类型对应的1字节中较小的一个,即1。

double类型对应8字节。

当最大成员(9)不是最大对齐数(8)的整数倍时,需要对齐到最大对齐数的整数倍(2倍,即16)。

union Data{
    int i;
    float f;
    char str[9];
    double d;
}data;

//该共用体内存大小为8 * 2 = 16 字节
union Data
{
    int i;
    float f;
    char str[20];
};
//最大对齐数为4
//最大成员大小为20,是4的整数倍
//故共用体大小为20字节

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值