0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

详解C/C++结构体、联合体和枚举的区别与内存对齐

冬至子 来源:AI让生活更美好 作者:Andy 2023-06-08 14:38 次阅读

C语言中构造类型一共有4种,它们分别是数组、结构体(struct)、共用体(union)、枚举类型(enum)。

图片

一、结构体类型

1、什么是结构体

在C语言中,结构体指的是一种数据结构,是C语言中聚合数据类型的一类。结构体可以被声明为变量、指针或数组等,用以实现较复杂的数据结构。结构体同时也是一些元素的集合,这些元素称为结构体的成员,且这些成员可以为不同的类型,成员一般用名字访问。也就是说,结构体是由多种原宿所构成的数据结构。

2、定义结构体类型

struct 结构体

{

任意类型 任意变量;

任意类型 任意变量;

……

};

注意:这不是定义变量,而是自定义一种类型而已。如:

struct student
{
char name[10];//学生姓名
int height;//学生身高
bool sex;//学生性别 假设0表示女,1表示男。
};

3、 定义结构体变量

类型定义好以后,则可以定义该类型的变量。

✔定义结构体变量:

struct student a,b;// struct可以省略。
可以在定义结构体变量的时候赋值。
如student a={”liudehua”,172,1},b={“lixiaolong”,172,1};

✔也可以在定义结构体变量以后赋值,但注意不能再用{}。如:

student a,b;
a={”liudehua”,172,1},b={“lixiaolong”,172,1};//这是错误的。

✔而应该是:

strcpy(a.name,”liudehua”);
a.height=172;
a.sex=1;

✔可以在定义结构体类型的时候同时定义结构体变量并赋值。

struct student
{
  char name[10];//学生姓名
  int height;//学生身高
  bool sex;//学生性别 假设0表示女,1表示男。
} a={”liudehua”,172,1},b={“aolong”,172,1};

4.访问结构体

访问结构体成员要用直接成员运算符“.”或间接成员运算符“->”。

#include < iostream >
struct student
{
    char name[10];//学生姓名
    int height;//学生身高
    bool sex;//学生性别 假设0表示女,1表示男。
}a={"liudehua",182,1},b={"aolong",188,1};


int main()
{
    struct student*  x;
    x=&a;
    std::cout<

对于结构体变量,访问其中的成员采取“结构体变量 . 成员”的形式;而对于结构体指针,访问它所指向的结构体变量中的成员,则采取“结构体指针->成员”形式。

二、联合体类型

1、什么是联合体

联合体也是一种自定义的复合类型,它可以包含多个不同类型的变量。这些变量在内存当中共用一段空间。这段空间的size就是各变量中size最大的那个变量。

2、定义联合体类型

union myunion
{
  int num1;
  double num2;
  float num3;
};

定义了一个联合体类型myunion。

myunion a,b;//定义了两个myunion型变量。

也可以在定义联合体类型的时候定义联合体变量。如:

union myunion
{
  int num1;
  double num2;
  float num3;
}a,b;

a占用的空间有多大呢?

Sizeof(a)结果即为8,即myunion占用8个字节,和double型变量相同。

注意:任一时刻,只能访问结构体里面的一个变量。

a.num1=2;
a.num2=3.154;
myunion *p;
p=&a;
p- >num3=5.6;

3、联合体的使用

C++的联合体(Union)与结构体相似,但它们的区别在于联合体中只能同时存储一个成员的值。这些成员共享同一个物理存储空间,也就是说,一个联合体的大小,等于它最大的成员变量所占据的空间。下面是一个示例代码:

#include < iostream >
using namespace std;

union Person {
   int age;
   float height;
   char name[50];
};


int main() {
   union Person p1;
   p1.age = 30;
   cout < < "Age: " < < p1.age < < endl;

   p1.height = 1.85;
   cout < < "Height: " < < p1.height < < endl;


   strcpy(p1.name, "John Doe");
   cout < < "Name: " < < p1.name < < endl;

   return 0;
}

在这个例子中,我们定义了一个名为“Person”的联合体,包含三个不同数据类型的成员变量:整数、浮点数和字符数组。在main函数中,我们可以看到如何使用联合体。在第一次赋值时,我们将age设置为30并输出,然后我们将height设置为1.85并输出,此时前一个赋值的值被覆盖了。在最后一部分,我们使用strcpy函数将字符串赋给name成员变量并输出。

需要注意的是,在实际应用联合体时,必须小心使用,因为一个成员变量的更改会影响所有其他成员变量。同时,由于联合体需要共享内存,因此必须确保联合体的大小能够容纳最大。

三、枚举类型

1、什么是枚举类型

枚举类型是一种数据类型,它通常用来定义一个数字常量集合。在枚举类型中,每个常量都有一个唯一的名称和对应的数值。

2、枚举类型的定义

枚举类型也是一种自定义的复合类型。不过,枚举类型中的成员都是常量。如

enum color
{
  red,
  green,
  blue,
  white,
  black
}

枚举类型中的成员默认值为从0开始,依次序递增。此时red==1,green为2,blue为3,white为4,black为5.

也可以改变起默认值。如

enum color
{
  red=1,
  green=3,
  blue=5,
  white,
  black
};

没有初始化的枚举类型成员的值将在它前面的成员基础上递增。所以,white的值为6,而black的值为7。

3、定义枚举变量

color a1,a2

4、给枚举变量赋值:

a1=red;
a2=blue;
cout< 

虽然枚举常量的值整数,但是不能直接将整数值赋给枚举变量。如

a1=1;//这是不对的。因为类型不匹配。一个是整型,一个是枚举类型。
a1=(color)1;//正确

枚举变量的size是一个整数的大小。

5、枚举的使用

在C++中,枚举类型可以用来定义一组常量。枚举为程序员提供了一种方便的方式去定义一些有意义的名称,而不是硬编码数字,这样代码更易于理解和维护。下面是一个基本的枚举示例:

#include < iostream >
using namespace std;




enum Weekday {
   Monday = 1,
   Tuesday,
   Wednesday,
   Thursday,
   Friday,
   Saturday,
   Sunday
};




int main() {
   Weekday today;
   today = Tuesday;

   if(today == Sunday){
      cout< < "Today is holiday!"<

在以上代码中,我们定义了一个Weekday枚举类型,将每个工作日映射到一个整数值上。默认情况下,第一个成员的值被设置为0,接着逐一自增,但我们可以使用显式赋值来覆盖它们。

在main函数中,我们声明了一个名为today的变量,并且将其设置为Tuesday,通过if-else语句检查是否为周日,然后输出结果。需要注意的是,枚举值可以与整数进行比较和赋值,因为每个成员都会被映射到一个整数值。

四、内存对齐与内存大小

1、内存对齐

在C语言中,内存对齐可以优化程序的性能,而结构体是需要进行内存对齐处理的数据类型。结构体的大小通常不仅取决于其中成员所占用的空间大小,还取决于操作系统和编译器对于内存对齐方式的处理。

具体地说,内存对齐方式是为了符合硬件平台访问内存数据的要求,并以此提高代码的执行效率。一般地,对于基本类型(如int、char、float等),系统通常会按照它们自身所占用的字节大小来进行内存分配,并确保各个变量在内存中的地址都是偶数或是四的倍数(这里假设系统采用的是32位架构)。

但如果结构体中的成员变量总大小不是4的倍数,则在结构体中填充一些无用的字节使得结构体字节数是4的倍数。

2、结构体大小

举例说明,假设有以下的结构体:

struct S1 
{
    char c1;   // 1 byte
    int i;    // 4 bytes
    char c2;  // 1 bytes
};
int main()
{
    std::cout< < sizeof (S1)<

图片

内存对齐示意图

它们总共占用的空间不是6字节(1+4+1),因为当前CPU硬件平台一次最小访问单位是4字节,所以编译器会自动进行内存补齐,使得每个成员的地址都是4的倍数,结构体的实际大小可能会是12字节(4字节对齐)或是8字节(1字节对齐)。所以,具体的内存大小可能会因编译器和硬件平台的不同而异,并且有些编译器可以通过一些指令来控制内存对齐方式以提高程序效率。

对于这中浪费内存的情况,作为程序员,我们在定义数据结构的时候完全可以避免。如下面:

struct S2 
{
    int i;    // 4 bytes
    char c1;   // 1 byte
    char c2;  // 1 bytes
};
int main()
{
    std::cout< < sizeof (S2)<

**通过改变结构体里面变量的顺序,避免内存对齐带来的空间浪费。内存大小变为了8,内存节省了4个字节大小。

**

3、联合体大小

C语言联合体(union)的内存大小取决于其中最大成员的大小。因为联合体内所有成员共用同一块内存区域,因此联合体的大小必须足够容纳所有成员中最大的那个。

举个例子,如果我们有一个联合体定义如下:

union Example 
{
    int x;
    char c;
    double d;
};

那么这个联合体的大小就是8个字节。因为这三个成员中最大的是double类型,占用8个字节,其他成员对齐到8个字节,所以整个联合体大小是8个字节。

需要注意的是,联合体的成员必须是同一种类型或者大小相同,这是因为它们会共用同一个内存区域。如果不同类型的成员共存,可能会导致数据覆盖或者读取数据时出现未定义的行为。所以在使用联合体时要特别小心,确保成员的类型和大小相同。

4、枚举类型大小

在C语言中,枚举类型(Enum)是一种自定义类型,用于表示有限个数的常量。在内存中,枚举类型通常被存储为整数类型,其大小与int类型相同,即通常为4个字节或8个字节(取决于系统架构)。

当定义枚举变量时,该变量的值由枚举列表中对应常量的整数值来决定。在下面这个例子中,我们创建了一个Color枚举类型,其中包含三个常量红色、绿色和蓝色,它们分别赋予值0、1和2。而变量c则被定义为Color类型并初始化为红色。

#include< stdio.h >
enum Color {
    RED,
    GREEN,
    BLUE
};


int main() {
    enum Color c = RED;
    printf("Sizeof enum: %d\\n", sizeof(enum Color));  //输出为4或8字节
    return 0;
}

需要注意的是,枚举类型在内存大小上可能会因为编译器实现和程序运行的机器体系结构所影响。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • C语言
    +关注

    关注

    180

    文章

    7604

    浏览量

    136706
  • 编译器
    +关注

    关注

    1

    文章

    1624

    浏览量

    49108
  • C++语言
    +关注

    关注

    0

    文章

    147

    浏览量

    6989
收藏 人收藏

    评论

    相关推荐

    C语言联合体的巧妙运用

    联合体(Union)是C语言中的一种复合类型,它允许在同一内存区域存储多个不同的数据类型的成员(member),但只能同时存在其中一个成员。
    发表于 06-21 10:59 1855次阅读

    430编程C语言常识(IAR)之结构联合体

      结构联合体C语言的常见数据类型,可对C的基本数据类型进行组合使之能表示复杂的数据结构
    发表于 11-22 15:43

    DLL导入结构 联合体

    DLL函数参数中,有结构联合体结构中使用联合体,这种方式的函数怎么使用LABVIEW导入
    发表于 09-06 10:32

    如何定义了这个联合体

    我先定义一个联合体数据类型,然后接着定义了一些联合体变量,定义联合体部分如下:我在sys_config.c文件中定义如下联合体数据类型和变量
    发表于 07-12 04:28

    为什么位域结构联合体一起使用?

    /*本例程是C语言的位域操作示例这里为什么位域结构联合体一起使用?-->因为这样定义后,即可以单独使用标志位 也可同时使用整个字节数据主要应用:单片机
    发表于 07-14 06:23

    结构联合体区别到底在哪里

    在单片机软件编程中,结构枚举类型都很常用到,联合体相对来用的就比较少。那么结构
    发表于 11-22 07:54

    如何利用联合体去判断大小端呢

    联合体的声明:利用联合体判断大小端先请看下列代码:由此,可以利用联合体判断大小端:同理,还有另一种方法判断大小端:联合大小的计算结构
    发表于 12-15 07:21

    测试结构成员内存对齐的方式方法

    //测试环境:keil for ARM//测试目的:通过keil仿真,介绍结构成员对齐方式 #pragma pack ()//定义一个联合体类型 struct stru {int a
    发表于 12-21 07:37

    联合体/共用的使用方法

    大家好,我是ZhengN。本次给分享联合体的一些知识。联合体/共用的使用 C语言中,联合体/共用
    发表于 02-28 10:05

    结构struct和联合体union的区别

    结构struct和联合体union的区别
    发表于 10-11 08:21

    C语言:结构联合体嵌套使用的实用操作

      结构联合体C语言中的构造类型,结构我们平时应该都用得很多。但是,对于
    的头像 发表于 12-24 16:07 5488次阅读
    <b class='flag-5'>C</b>语言:<b class='flag-5'>结构</b><b class='flag-5'>体</b>、<b class='flag-5'>联合体</b>嵌套使用的实用操作

    什么是C语言的联合体

    名{ 成员列表 }; 共用有时也被称为联合或者联合体,这也是 Union 这个单词的本意。 结构
    的头像 发表于 07-29 15:35 3734次阅读
    什么是<b class='flag-5'>C</b>语言的<b class='flag-5'>联合体</b>

    c语言中结构联合体区别

    结构联合体C语言中的构造类型,结构我们平时应该都用得很多。但是,对于
    的头像 发表于 12-03 14:25 2490次阅读
    <b class='flag-5'>c</b>语言中<b class='flag-5'>结构</b><b class='flag-5'>体</b>有<b class='flag-5'>联合体</b>的<b class='flag-5'>区别</b>

    看一下结构联合体结合使用在C语言与嵌入式中的一些实用技巧

    结构联合体C语言中的构造类型,结构我们平时应该都用得很多。但是,对于
    发表于 05-08 10:19 4260次阅读
    看一下<b class='flag-5'>结构</b><b class='flag-5'>体</b>、<b class='flag-5'>联合体</b>结合使用在<b class='flag-5'>C</b>语言与嵌入式中的一些实用技巧

    经典 C 语言编程,结构联合体如何共用?

    中可以 使用 sizeof 进行获取,默认为字节对齐的大小。 联合体 联合体的参数共享同一个内存地址,所占的内存大小完全是由
    的头像 发表于 01-11 18:24 1355次阅读
    经典 <b class='flag-5'>C</b> 语言编程,<b class='flag-5'>结构</b><b class='flag-5'>体</b>和<b class='flag-5'>联合体</b>如何共用?