C语言教程(十一)结构体与联合体

1. 简介

结构体是一种复合数据类型,它不同于数组,允许将不同类型的数据包含在内组成一个复合的数据类型。C语言中使用struct关键字来表示结构体,同时允许程序员自定义结构体,这使得C语言更加地灵活编程。

但是它不同于面向对象中的类的概念,结构体内只有不同类型的属性,没有方法。

联合体也是一种复合的数据类型,它允许在相同的位置存储不同的数据,C语言中使用union关键字来表示,联合体内的成员不具有单独的内存空间,都是共享内存空间的,也就是说同一时刻只能存储一个值。

2. struct结构体

2.1 struct的声明与初始化

结构体使用struct关键字来定义,可以包含任何基本数据类型及其他复合数据类型。

struct person{  //定义一个结构体person
   char name[20];
   int age;
   int height;
};

上面的示例中,使用关键字struct定义了一个名为person的结构体类型,包含三个不同类型的成员,结构体结尾的分号不要忘记写上。

结构体类型定义好之后,就可以声明结构体类型的变量,然后对结构体内的成员进行初始化。

struct person person1;
person1.name = "小明";
person1.age = 18;
person1.height = 180;
//等同于
struct person person1 = {"小明",18,180};

上面的示例是结构体person的变量声明以及初始化的两种方式,使用大括号{}对成员赋值时,必须与声明时的成员顺序一致,除非是指定成员初始化;如果缺失成员的初始化,会自动初始化为0,和数组一样。

struct person person1 = {.age = 18,.name = "小明"};//指定成员赋值
//等同于
struct person person1 = {.age = 18,.name = "小明".height = 0};//初始化为0

结构体类型的定义与变量声明可以合并在一起。

struct person{  //定义一个结构体person
   char name[20];
   int age;
   int height;
}person1;

如果定义类型与变量声明合并在一起,则允许省略类型名称,定义匿名的结构体类型。

struct{  //定义一个结构体person
   char name[20];
   int age;
   int height;
}person1;

结构体数据类型还可以支持类型定义、变量声明、初始化写在一起。

struct{  //定义一个结构体person
   char name[20];
   int age;
   int height;
}person1 = {"小明",18,180};

2.2 结构体指针

结构体也是数据类型,也可以声明为指针变量,让指针变量指向结构体类型。

struct person{  //定义一个结构体person
   char name[20];
   int age;
   int height;
}*person1;//指针变量指向结构体类型

//等同于
struct person{  //定义一个结构体person
   char name[20];
   int age;
   int height;
};
struct person *person1;

结构体类型可以作为函数的参数传递,可以是值传递,也可以是指针传递。通常情况下,使用指针变量作为参数,不必创建一个结构体副本,避免了复制整个结构体到内存空间。

struct person{  //定义一个结构体person
   char name[20];
   int age;
   int height;
};
//传入结构体类型
void func(struct person person1){  
   person1.age = 18;
}
struct person person1 = {"小明",18,180};
func(person1);

//传入结构体指针
void func(struct person *person1){
     (*person1).age = 18;//等同于person1->age
}
struct person person1 = {"小明",18,180};
func(&person1);

上面的示例中,分别展现了值传递和指针传递的两种方式,值传递时传递的是结构体的副本,修改结构体的数据时不会影响原结构体的值,但是效率会低下;如果是指针传递的话,则是传入的是结构体的地址,即同一个结构体,这样的话只需要操作指针即可,无需把整个结构体都复制到栈中,提高了程序的性能。

传入结构体指针时,就需要使用(*person1)先取值,再使用.符号获取成员,这样写会很麻烦;C语言提供一种更便捷的方式,使用->符号获取结构体成员,比如person1->age。

另外,使用结构体指针作为函数参数时,在函数调用时,实参要传入指针变量的地址。

2.3 结构体位域

C语言中,结构体内的成员支持以二进制位为单位定义,可以自由控制结构体所占用的内存空间,这就是结构体的位域成员(bit field)。位域成员再定义时需要指定所占用的位数。

struct s{//定义含有位域成员的结构体
   int a:1;
   int b:2;
   int c:3;
   int  :4;//匿名位域,跳过4位
}s1;

上面的示例中定义了一个结构体类型s,含有4个位域成员,前面是类型和位域名称,冒号后面是占用的位数,如果相邻的位域成员类型相同且总位数没有超过类型的大小,则会连续存储;如果超过了类型的大小(包含匿名位域),就从新的内存单元开始存储。上面的int类型是32位且相邻,所以位域会连续存储。

3. union联合体

3.1 union声明与初始化

C语言使用union关键字来定义联合体类型,和结构体类似,都可以定义不同类型的数据。union联合体内的成员共享同一块内存空间,联合体的大小是最大成员的大小,而非所有成员的总和。

union u{//定义一个联合体类型
   int i;
   float f;
   char c[10];
};

上面示例中,使用union关键字定义了联合体u,包含三个不同类型的成员。同样和结构体一样,也需要声明变量并初始化,也是用.符号来访问联合体成员。

union u u1;//声明union变量

//初始化
u1.i = 1;
u1.f = 1.2;
u1.c = "C";

联合体变量声明和初始化也可以合并在一起,如果不指定成员名,默认赋值给第一个成员。

union u u1 = {.i = 1};//指定成员初始化

union u u1 = {1};//不指定成员默认初始化第一个成员,即i

3.2 联合体指针

和结构体一样,联合体也可以声明为指针变量,使指针指向联合体,也是使用->符号访问联合体成员。

union u{
   int i;
   float f;
   char c[10];
};
union u *u1;//声明联合体指针
u1->i = 1;//访问联合体成员

4. 结构体与联合体的区别

  • 结构体类型使用struct关键字定义,而联合体类型使用union关键字定义;
  • 结构体类型中的每个成员都有独立的内存空间,联合体类型的成员是共享内存,大小是最大成员的大小;
  • 结构体类型中的大小是所有成员的总和(对齐原则),联合体类型的大小是最大成员的大小。
觉得有帮助可以赞赏本文哦~万分感谢!
文章:C语言教程(十一)结构体与联合体
作者:沛旗
链接:https://www.peiqiblog.com/article/2666/
版权声明::本博客站点所有文章除特别声明外,均采用 CC BY-NC-SA 4.0协议
转载请注明文章地址及作者哦~
暂无评论

发送评论(禁止发表一切违反法律法规的敏感言论) 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇