0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

詳解C/C++結(jié)構(gòu)體、聯(lián)合體和枚舉的區(qū)別與內(nèi)存對(duì)齊

冬至子 ? 來(lái)源:AI讓生活更美好 ? 作者:Andy ? 2023-06-08 14:38 ? 次閱讀

C語(yǔ)言中構(gòu)造類(lèi)型一共有4種,它們分別是數(shù)組、結(jié)構(gòu)體(struct)、共用體(union)、枚舉類(lèi)型(enum)。

圖片

一、結(jié)構(gòu)體類(lèi)型

1、什么是結(jié)構(gòu)體

在C語(yǔ)言中,結(jié)構(gòu)體指的是一種數(shù)據(jù)結(jié)構(gòu),是C語(yǔ)言中聚合數(shù)據(jù)類(lèi)型的一類(lèi)。結(jié)構(gòu)體可以被聲明為變量、指針或數(shù)組等,用以實(shí)現(xiàn)較復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。結(jié)構(gòu)體同時(shí)也是一些元素的集合,這些元素稱為結(jié)構(gòu)體的成員,且這些成員可以為不同的類(lèi)型,成員一般用名字訪問(wèn)。也就是說(shuō),結(jié)構(gòu)體是由多種原宿所構(gòu)成的數(shù)據(jù)結(jié)構(gòu)。

2、定義結(jié)構(gòu)體類(lèi)型

struct 結(jié)構(gòu)體

{

任意類(lèi)型 任意變量;

任意類(lèi)型 任意變量;

……

};

注意:這不是定義變量,而是自定義一種類(lèi)型而已。如:

struct student
{
char name[10];//學(xué)生姓名
int height;//學(xué)生身高
bool sex;//學(xué)生性別 假設(shè)0表示女,1表示男。
};

3、 定義結(jié)構(gòu)體變量

類(lèi)型定義好以后,則可以定義該類(lèi)型的變量。

?定義結(jié)構(gòu)體變量:

struct student a,b;// struct可以省略。
可以在定義結(jié)構(gòu)體變量的時(shí)候賦值。
如student a={”liudehua”,172,1},b={“l(fā)ixiaolong”,172,1};

?也可以在定義結(jié)構(gòu)體變量以后賦值,但注意不能再用{}。如:

student a,b;
a={”liudehua”,172,1},b={“l(fā)ixiaolong”,172,1};//這是錯(cuò)誤的。

?而應(yīng)該是:

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

?可以在定義結(jié)構(gòu)體類(lèi)型的時(shí)候同時(shí)定義結(jié)構(gòu)體變量并賦值。

struct student
{
  char name[10];//學(xué)生姓名
  int height;//學(xué)生身高
  bool sex;//學(xué)生性別 假設(shè)0表示女,1表示男。
} a={”liudehua”,172,1},b={“aolong”,172,1};

4.訪問(wèn)結(jié)構(gòu)體

訪問(wèn)結(jié)構(gòu)體成員要用直接成員運(yùn)算符“.”或間接成員運(yùn)算符“->”。

#include < iostream >
struct student
{
    char name[10];//學(xué)生姓名
    int height;//學(xué)生身高
    bool sex;//學(xué)生性別 假設(shè)0表示女,1表示男。
}a={"liudehua",182,1},b={"aolong",188,1};


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

對(duì)于結(jié)構(gòu)體變量,訪問(wèn)其中的成員采取“結(jié)構(gòu)體變量 . 成員”的形式;而對(duì)于結(jié)構(gòu)體指針,訪問(wèn)它所指向的結(jié)構(gòu)體變量中的成員,則采取“結(jié)構(gòu)體指針->成員”形式。

二、聯(lián)合體類(lèi)型

1、什么是聯(lián)合體

聯(lián)合體也是一種自定義的復(fù)合類(lèi)型,它可以包含多個(gè)不同類(lèi)型的變量。這些變量在內(nèi)存當(dāng)中共用一段空間。這段空間的size就是各變量中size最大的那個(gè)變量。

2、定義聯(lián)合體類(lèi)型

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

定義了一個(gè)聯(lián)合體類(lèi)型myunion。

myunion a,b;//定義了兩個(gè)myunion型變量。

也可以在定義聯(lián)合體類(lèi)型的時(shí)候定義聯(lián)合體變量。如:

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

a占用的空間有多大呢?

Sizeof(a)結(jié)果即為8,即myunion占用8個(gè)字節(jié),和double型變量相同。

注意:任一時(shí)刻,只能訪問(wèn)結(jié)構(gòu)體里面的一個(gè)變量。

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

3、聯(lián)合體的使用

C++的聯(lián)合體(Union)與結(jié)構(gòu)體相似,但它們的區(qū)別在于聯(lián)合體中只能同時(shí)存儲(chǔ)一個(gè)成員的值。這些成員共享同一個(gè)物理存儲(chǔ)空間,也就是說(shuō),一個(gè)聯(lián)合體的大小,等于它最大的成員變量所占據(jù)的空間。下面是一個(gè)示例代碼:

#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;
}

在這個(gè)例子中,我們定義了一個(gè)名為“Person”的聯(lián)合體,包含三個(gè)不同數(shù)據(jù)類(lèi)型的成員變量:整數(shù)、浮點(diǎn)數(shù)和字符數(shù)組。在main函數(shù)中,我們可以看到如何使用聯(lián)合體。在第一次賦值時(shí),我們將age設(shè)置為30并輸出,然后我們將height設(shè)置為1.85并輸出,此時(shí)前一個(gè)賦值的值被覆蓋了。在最后一部分,我們使用strcpy函數(shù)將字符串賦給name成員變量并輸出。

需要注意的是,在實(shí)際應(yīng)用聯(lián)合體時(shí),必須小心使用,因?yàn)橐粋€(gè)成員變量的更改會(huì)影響所有其他成員變量。同時(shí),由于聯(lián)合體需要共享內(nèi)存,因此必須確保聯(lián)合體的大小能夠容納最大。

三、枚舉類(lèi)型

1、什么是枚舉類(lèi)型

枚舉類(lèi)型是一種數(shù)據(jù)類(lèi)型,它通常用來(lái)定義一個(gè)數(shù)字常量集合。在枚舉類(lèi)型中,每個(gè)常量都有一個(gè)唯一的名稱和對(duì)應(yīng)的數(shù)值。

2、枚舉類(lèi)型的定義

枚舉類(lèi)型也是一種自定義的復(fù)合類(lèi)型。不過(guò),枚舉類(lèi)型中的成員都是常量。如

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

枚舉類(lèi)型中的成員默認(rèn)值為從0開(kāi)始,依次序遞增。此時(shí)red==1,green為2,blue為3,white為4,black為5.

也可以改變起默認(rèn)值。如

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

沒(méi)有初始化的枚舉類(lèi)型成員的值將在它前面的成員基礎(chǔ)上遞增。所以,white的值為6,而black的值為7。

3、定義枚舉變量

color a1,a2

4、給枚舉變量賦值:

a1=red;
a2=blue;
cout

雖然枚舉常量的值整數(shù),但是不能直接將整數(shù)值賦給枚舉變量。如

a1=1;//這是不對(duì)的。因?yàn)轭?lèi)型不匹配。一個(gè)是整型,一個(gè)是枚舉類(lèi)型。
a1=(color)1;//正確

枚舉變量的size是一個(gè)整數(shù)的大小。

5、枚舉的使用

在C++中,枚舉類(lèi)型可以用來(lái)定義一組常量。枚舉為程序員提供了一種方便的方式去定義一些有意義的名稱,而不是硬編碼數(shù)字,這樣代碼更易于理解和維護(hù)。下面是一個(gè)基本的枚舉示例:

#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!"<

在以上代碼中,我們定義了一個(gè)Weekday枚舉類(lèi)型,將每個(gè)工作日映射到一個(gè)整數(shù)值上。默認(rèn)情況下,第一個(gè)成員的值被設(shè)置為0,接著逐一自增,但我們可以使用顯式賦值來(lái)覆蓋它們。

在main函數(shù)中,我們聲明了一個(gè)名為today的變量,并且將其設(shè)置為T(mén)uesday,通過(guò)if-else語(yǔ)句檢查是否為周日,然后輸出結(jié)果。需要注意的是,枚舉值可以與整數(shù)進(jìn)行比較和賦值,因?yàn)槊總€(gè)成員都會(huì)被映射到一個(gè)整數(shù)值。

四、內(nèi)存對(duì)齊與內(nèi)存大小

1、內(nèi)存對(duì)齊

在C語(yǔ)言中,內(nèi)存對(duì)齊可以優(yōu)化程序的性能,而結(jié)構(gòu)體是需要進(jìn)行內(nèi)存對(duì)齊處理的數(shù)據(jù)類(lèi)型。結(jié)構(gòu)體的大小通常不僅取決于其中成員所占用的空間大小,還取決于操作系統(tǒng)和編譯器對(duì)于內(nèi)存對(duì)齊方式的處理。

具體地說(shuō),內(nèi)存對(duì)齊方式是為了符合硬件平臺(tái)訪問(wèn)內(nèi)存數(shù)據(jù)的要求,并以此提高代碼的執(zhí)行效率。一般地,對(duì)于基本類(lèi)型(如int、char、float等),系統(tǒng)通常會(huì)按照它們自身所占用的字節(jié)大小來(lái)進(jìn)行內(nèi)存分配,并確保各個(gè)變量在內(nèi)存中的地址都是偶數(shù)或是四的倍數(shù)(這里假設(shè)系統(tǒng)采用的是32位架構(gòu))。

但如果結(jié)構(gòu)體中的成員變量總大小不是4的倍數(shù),則在結(jié)構(gòu)體中填充一些無(wú)用的字節(jié)使得結(jié)構(gòu)體字節(jié)數(shù)是4的倍數(shù)。

2、結(jié)構(gòu)體大小

舉例說(shuō)明,假設(shè)有以下的結(jié)構(gòu)體:

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

圖片

內(nèi)存對(duì)齊示意圖

它們總共占用的空間不是6字節(jié)(1+4+1),因?yàn)楫?dāng)前CPU硬件平臺(tái)一次最小訪問(wèn)單位是4字節(jié),所以編譯器會(huì)自動(dòng)進(jìn)行內(nèi)存補(bǔ)齊,使得每個(gè)成員的地址都是4的倍數(shù),結(jié)構(gòu)體的實(shí)際大小可能會(huì)是12字節(jié)(4字節(jié)對(duì)齊)或是8字節(jié)(1字節(jié)對(duì)齊)。所以,具體的內(nèi)存大小可能會(huì)因編譯器和硬件平臺(tái)的不同而異,并且有些編譯器可以通過(guò)一些指令來(lái)控制內(nèi)存對(duì)齊方式以提高程序效率。

對(duì)于這中浪費(fèi)內(nèi)存的情況,作為程序員,我們?cè)诙x數(shù)據(jù)結(jié)構(gòu)的時(shí)候完全可以避免。如下面:

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

**通過(guò)改變結(jié)構(gòu)體里面變量的順序,避免內(nèi)存對(duì)齊帶來(lái)的空間浪費(fèi)。內(nèi)存大小變?yōu)榱?,內(nèi)存節(jié)省了4個(gè)字節(jié)大小。

**

3、聯(lián)合體大小

C語(yǔ)言聯(lián)合體(union)的內(nèi)存大小取決于其中最大成員的大小。因?yàn)槁?lián)合體內(nèi)所有成員共用同一塊內(nèi)存區(qū)域,因此聯(lián)合體的大小必須足夠容納所有成員中最大的那個(gè)。

舉個(gè)例子,如果我們有一個(gè)聯(lián)合體定義如下:

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

那么這個(gè)聯(lián)合體的大小就是8個(gè)字節(jié)。因?yàn)檫@三個(gè)成員中最大的是double類(lèi)型,占用8個(gè)字節(jié),其他成員對(duì)齊到8個(gè)字節(jié),所以整個(gè)聯(lián)合體大小是8個(gè)字節(jié)。

需要注意的是,聯(lián)合體的成員必須是同一種類(lèi)型或者大小相同,這是因?yàn)樗鼈儠?huì)共用同一個(gè)內(nèi)存區(qū)域。如果不同類(lèi)型的成員共存,可能會(huì)導(dǎo)致數(shù)據(jù)覆蓋或者讀取數(shù)據(jù)時(shí)出現(xiàn)未定義的行為。所以在使用聯(lián)合體時(shí)要特別小心,確保成員的類(lèi)型和大小相同。

4、枚舉類(lèi)型大小

在C語(yǔ)言中,枚舉類(lèi)型(Enum)是一種自定義類(lèi)型,用于表示有限個(gè)數(shù)的常量。在內(nèi)存中,枚舉類(lèi)型通常被存儲(chǔ)為整數(shù)類(lèi)型,其大小與int類(lèi)型相同,即通常為4個(gè)字節(jié)或8個(gè)字節(jié)(取決于系統(tǒng)架構(gòu))。

當(dāng)定義枚舉變量時(shí),該變量的值由枚舉列表中對(duì)應(yīng)常量的整數(shù)值來(lái)決定。在下面這個(gè)例子中,我們創(chuàng)建了一個(gè)Color枚舉類(lèi)型,其中包含三個(gè)常量紅色、綠色和藍(lán)色,它們分別賦予值0、1和2。而變量c則被定義為Color類(lèi)型并初始化為紅色。

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


int main() {
    enum Color c = RED;
    printf("Sizeof enum: %d\\n", sizeof(enum Color));  //輸出為4或8字節(jié)
    return 0;
}

需要注意的是,枚舉類(lèi)型在內(nèi)存大小上可能會(huì)因?yàn)榫幾g器實(shí)現(xiàn)和程序運(yùn)行的機(jī)器體系結(jié)構(gòu)所影響。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • C語(yǔ)言
    +關(guān)注

    關(guān)注

    180

    文章

    7594

    瀏覽量

    135862
  • 編譯器
    +關(guān)注

    關(guān)注

    1

    文章

    1617

    瀏覽量

    49015
  • C++語(yǔ)言
    +關(guān)注

    關(guān)注

    0

    文章

    147

    瀏覽量

    6951
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    C語(yǔ)言聯(lián)合體的巧妙運(yùn)用

    聯(lián)合體(Union)是C語(yǔ)言中的一種復(fù)合類(lèi)型,它允許在同一內(nèi)存區(qū)域存儲(chǔ)多個(gè)不同的數(shù)據(jù)類(lèi)型的成員(member),但只能同時(shí)存在其中一個(gè)成員。
    發(fā)表于 06-21 10:59 ?1759次閱讀

    430編程C語(yǔ)言常識(shí)(IAR)之結(jié)構(gòu)聯(lián)合體

      結(jié)構(gòu)聯(lián)合體C語(yǔ)言的常見(jiàn)數(shù)據(jù)類(lèi)型,可對(duì)C的基本數(shù)據(jù)類(lèi)型進(jìn)行組合使之能表示復(fù)雜的數(shù)據(jù)結(jié)構(gòu),
    發(fā)表于 11-22 15:43

    DLL導(dǎo)入結(jié)構(gòu) 聯(lián)合體

    DLL函數(shù)參數(shù)中,有結(jié)構(gòu)聯(lián)合體,結(jié)構(gòu)中使用聯(lián)合體,這種方式的函數(shù)怎么使用LABVIEW導(dǎo)入
    發(fā)表于 09-06 10:32

    如何定義了這個(gè)聯(lián)合體?

    我先定義一個(gè)聯(lián)合體數(shù)據(jù)類(lèi)型,然后接著定義了一些聯(lián)合體變量,定義聯(lián)合體部分如下:我在sys_config.c文件中定義如下聯(lián)合體數(shù)據(jù)類(lèi)型和變量
    發(fā)表于 07-12 04:28

    為什么位域結(jié)構(gòu)聯(lián)合體一起使用?

    /*本例程是C語(yǔ)言的位域操作示例這里為什么位域結(jié)構(gòu)聯(lián)合體一起使用?-->因?yàn)檫@樣定義后,即可以單獨(dú)使用標(biāo)志位 也可同時(shí)使用整個(gè)字節(jié)數(shù)據(jù)主要應(yīng)用:?jiǎn)纹瑱C(jī)
    發(fā)表于 07-14 06:23

    結(jié)構(gòu)聯(lián)合體區(qū)別到底在哪里

    在單片機(jī)軟件編程中,結(jié)構(gòu)枚舉類(lèi)型都很常用到,聯(lián)合體相對(duì)來(lái)用的就比較少。那么結(jié)構(gòu)
    發(fā)表于 11-22 07:54

    如何利用聯(lián)合體去判斷大小端呢

    聯(lián)合體的聲明:利用聯(lián)合體判斷大小端先請(qǐng)看下列代碼:由此,可以利用聯(lián)合體判斷大小端:同理,還有另一種方法判斷大小端:聯(lián)合大小的計(jì)算結(jié)構(gòu)
    發(fā)表于 12-15 07:21

    測(cè)試結(jié)構(gòu)成員內(nèi)存對(duì)齊的方式方法

    //測(cè)試環(huán)境:keil for ARM//測(cè)試目的:通過(guò)keil仿真,介紹結(jié)構(gòu)成員對(duì)齊方式 #pragma pack ()//定義一個(gè)聯(lián)合體類(lèi)型 struct stru {int a
    發(fā)表于 12-21 07:37

    聯(lián)合體/共用的使用方法

    大家好,我是ZhengN。本次給分享聯(lián)合體的一些知識(shí)。聯(lián)合體/共用的使用 C語(yǔ)言中,聯(lián)合體/共用
    發(fā)表于 02-28 10:05

    結(jié)構(gòu)struct和聯(lián)合體union的區(qū)別?

    結(jié)構(gòu)struct和聯(lián)合體union的區(qū)別
    發(fā)表于 10-11 08:21

    C語(yǔ)言:結(jié)構(gòu)、聯(lián)合體嵌套使用的實(shí)用操作

    ? 結(jié)構(gòu)、聯(lián)合體C語(yǔ)言中的構(gòu)造類(lèi)型,結(jié)構(gòu)我們平時(shí)應(yīng)該都用得很多。但是,對(duì)于
    的頭像 發(fā)表于 12-24 16:07 ?5430次閱讀
    <b class='flag-5'>C</b>語(yǔ)言:<b class='flag-5'>結(jié)構(gòu)</b><b class='flag-5'>體</b>、<b class='flag-5'>聯(lián)合體</b>嵌套使用的實(shí)用操作

    什么是C語(yǔ)言的聯(lián)合體

    名{ 成員列表 }; 共用有時(shí)也被稱為聯(lián)合或者聯(lián)合體,這也是 Union 這個(gè)單詞的本意。 結(jié)構(gòu)
    的頭像 發(fā)表于 07-29 15:35 ?3667次閱讀
    什么是<b class='flag-5'>C</b>語(yǔ)言的<b class='flag-5'>聯(lián)合體</b>

    c語(yǔ)言中結(jié)構(gòu)聯(lián)合體區(qū)別

    結(jié)構(gòu)、聯(lián)合體C語(yǔ)言中的構(gòu)造類(lèi)型,結(jié)構(gòu)我們平時(shí)應(yīng)該都用得很多。但是,對(duì)于
    的頭像 發(fā)表于 12-03 14:25 ?2452次閱讀
    <b class='flag-5'>c</b>語(yǔ)言中<b class='flag-5'>結(jié)構(gòu)</b><b class='flag-5'>體</b>有<b class='flag-5'>聯(lián)合體</b>的<b class='flag-5'>區(qū)別</b>

    看一下結(jié)構(gòu)聯(lián)合體結(jié)合使用在C語(yǔ)言與嵌入式中的一些實(shí)用技巧

    結(jié)構(gòu)、聯(lián)合體C語(yǔ)言中的構(gòu)造類(lèi)型,結(jié)構(gòu)我們平時(shí)應(yīng)該都用得很多。但是,對(duì)于
    發(fā)表于 05-08 10:19 ?4216次閱讀
    看一下<b class='flag-5'>結(jié)構(gòu)</b><b class='flag-5'>體</b>、<b class='flag-5'>聯(lián)合體</b>結(jié)合使用在<b class='flag-5'>C</b>語(yǔ)言與嵌入式中的一些實(shí)用技巧

    經(jīng)典 C 語(yǔ)言編程,結(jié)構(gòu)聯(lián)合體如何共用?

    中可以 使用 sizeof 進(jìn)行獲取,默認(rèn)為字節(jié)對(duì)齊的大小。 聯(lián)合體 聯(lián)合體的參數(shù)共享同一個(gè)內(nèi)存地址,所占的內(nèi)存大小完全是由
    的頭像 發(fā)表于 01-11 18:24 ?1231次閱讀
    經(jīng)典 <b class='flag-5'>C</b> 語(yǔ)言編程,<b class='flag-5'>結(jié)構(gòu)</b><b class='flag-5'>體</b>和<b class='flag-5'>聯(lián)合體</b>如何共用?