免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
【C語言經(jīng)典編程技術(shù)】C語言中union與struct的區(qū)別及sizeof的計算方式

C語言中union與struct的區(qū)別

在C語言中結(jié)構(gòu)體和聯(lián)合具有細微差別,特別是使用sizeof()對其求大小時,許多剛剛接觸C語言不久的朋友對此非常困惑,下面我將簡單談一下自己對union與struct之間的區(qū)別

聯(lián) 合(union) 
1. 聯(lián)合說明和聯(lián)合變量定義 
聯(lián)合也是一種新的數(shù)據(jù)類型, 它是一種特殊形式的變量。 
聯(lián)合說明和聯(lián)合變量定義與結(jié)構(gòu)十分相似。其形式為: 
union 聯(lián)合名{ 
數(shù)據(jù)類型 成員名; 
數(shù)據(jù)類型 成員名; 
... 
} 聯(lián)合變量名; 
聯(lián)合表示幾個變量共用一個內(nèi)存位置, 在不同的時間保存不同的數(shù)據(jù)類型 和不同長度的變量。 

union A
{
   int a[5];
   char b;
   double c;   
}Air;

表示聲明了一個名稱為A的聯(lián)合,可以使用A  variable 來定義聯(lián)合變量。

在聯(lián)合變量 variable中 整型和字符型以及double型共用同一內(nèi)存位置。

當(dāng)一個聯(lián)合被說明時, 編譯程序自動地產(chǎn)生一個變量, 其長度為聯(lián)合中最大的變量長度。 
聯(lián)合訪問其成員的方法與結(jié)構(gòu)相同。同樣聯(lián)合變量也可以定義成數(shù)組或指針,但定義為指針時, 也要用'->'符號, 此時聯(lián)合訪問成員可表示成: 
聯(lián)合名->成員名 
另外, 聯(lián)合既可以出現(xiàn)在結(jié)構(gòu)內(nèi), 它的成員也可以是結(jié)構(gòu)。  

 union
 {
   int i;
   struct
   {
  char first;
  char second;
 }half;
  }number;

2.結(jié)構(gòu)的定義

定義一個結(jié)構(gòu)的一般形式為: 
struct 結(jié)構(gòu)名 

成員表列 
};
成員表由若干個成員組成, 每個成員都是該結(jié)構(gòu)的一個組成部分。對每個成員也必須作類型說明,其形式為:
類型說明符 成員名; 
成員名的命名應(yīng)符合標識符的書寫規(guī)定。例如: 
struct stu
{
int num;
char name[20];
char sex;
float score;
}; 
在這個結(jié)構(gòu)定義中,結(jié)構(gòu)名為stu,該結(jié)構(gòu)由4個成員組成。第一個成員為num,整型變量;第二個成員為name,字符數(shù)組;第三個成員為 sex,字符變量;第四個成員為score,實型變量。應(yīng)注意在括號后的分號是不可少的。結(jié)構(gòu)定義之后,即可進行變量說明。凡說明為結(jié)構(gòu)stu的變量都由上述4個成員組成。由此可見, 結(jié)構(gòu)是一種復(fù)雜的數(shù)據(jù)類型,是數(shù)目固定,類型不同的若干有序變量的集合。

在介紹了結(jié)構(gòu)和聯(lián)合的基本知識后,我們開始今天要講的關(guān)于sizeof對結(jié)構(gòu)體和聯(lián)合求值問題:

讓我們來看一道華為的面試題:

 例:設(shè)有以下說明和定義: 

typedef  union   {long   i;   int  k[5];   char   c;} DATE; 
struct  data   {   int   cat;  DATE   cow;   double   dog;}   too; 
DATE   max; 
則語句   printf( '%d',sizeof(struct   date)+sizeof(max));的執(zhí)行結(jié)果是:____

需要說明的是typedef只是一個簡單的名字替換,方便系統(tǒng)在不同的平臺上移植,請參考以下例子:

#include <stdio.h>
#include <stdlib.h> 
int main()
{
  typedef  int Example;
  Example a=10;//Equals to int a=10;
  printf('%d\n',a);
 system('pause');
}

解釋:假設(shè)為32位機器,那么DATE是一個union,   變量公用空間.   里面最大的變量類型是int[5],   占用20個字節(jié).   所以它的大小是20,data是一個struct,每個變量分開占用空間.依次為int4   +   DATE20   +   double8   =   32. 所以結(jié)果是   20   +   32   =  52.

再看下例:

設(shè)有以下說明和定義: 
typedef  union   {double   i;   int  k[5];   char   c;} DATE; 
struct  data   {   int   cat;  DATE   cow;   double   dog;}   too; 
DATE   max; 
則語句   printf( '%d',sizeof(struct   date)+sizeof(max));的執(zhí)行結(jié)果是:____

在草率回答這一問題之前我們先看一個小例子:

#include <stdio.h>
#include <stdlib.h> 
union A
{
int a[5];
char b;
double c;
};
int main()
{
   printf('%d\n',sizeof(A));
   system('pause');
}

對A用sizeof輸出卻得到的是24!union中變量共用內(nèi)存,應(yīng)以最長的為準,可是結(jié)果卻不是我們預(yù)想的20,這是因為在聯(lián)合內(nèi)變量的默認內(nèi)存對其方式,必須以最長的double8字節(jié)對齊,也就是說故應(yīng)該是sizeof(A)=24;所以我們將聯(lián)合中的int a[5] 修改成 int a[6] 結(jié)果仍然不變,但如果我們將int a[5]修改成 int a[7],結(jié)果就變成了 32了。

C語言sizeOf() 結(jié)構(gòu)體對齊策略

struct AA

{
    int num,*a;
    char d;
    double e;
}; 
   int i1 = sizeof(int);//占用4個字節(jié)
   int i2 = sizeof(int*);//占用4個字節(jié)
   int i3 = sizeof(char);//占用1個字節(jié)
   int i4 = sizeof(double);//占用8個字節(jié)
   int i5 = sizeof(AA);//占用24字節(jié)

 為什么結(jié)構(gòu)體AA不是只用其成員的總和值4+4+1+8呢?

因為根據(jù)Win32平臺下的微軟 編譯器(cl.exe for 80×86)的對齊策略:

1) 結(jié)構(gòu)體變量的首地址能夠被其最寬基本類型成員的大小所整除;
備注:編譯器在給結(jié)構(gòu)體開辟空間時,首先找到結(jié)構(gòu)體中最寬的基本數(shù)據(jù)類型,然后尋找內(nèi)存地址能被該基本數(shù)據(jù)類型所整除的位置,作為結(jié)構(gòu)體的首地址。將這個最寬的基本數(shù)據(jù)類型的大小作為上面介紹的對齊模數(shù)。
2) 結(jié)構(gòu)體每個成員相對于結(jié)構(gòu)體首地址的偏移量(offset)都是成員大小的整數(shù)倍,如有需要編譯器會在成員之間加上填充字節(jié)(internal adding);
備注:為結(jié)構(gòu)體的一個成員開辟空間之前,編譯器首先檢查預(yù)開辟空間的首地址相對于結(jié)構(gòu)體首地址的偏移是否是本成員的整數(shù)倍,若是,則存放本成員,反之,則在本成員和上一個成員之間填充一定的字節(jié),以達到整數(shù)倍的要求,也就是將預(yù)開辟空間的首地址后移幾個字節(jié)。
3) 結(jié)構(gòu)體的總大小為結(jié)構(gòu)體最寬基本類型成員大小的整數(shù)倍,如有需要,編譯器會在最末一個成員之后加上填充字節(jié)(trailing padding)。
備注:結(jié)構(gòu)體總大小是包括填充字節(jié),最后一個成員滿足上面兩條以外,還必須滿足第三條,否則就必須在最后填充幾個字節(jié)以達到本條要求。

是不是有點云里霧里呢?那讓我們一起來遵循規(guī)律看下來吧

其中int i1 = sizeof(int)//偏移量為0 占用4個字節(jié)的長度

int i2 = sizeof(int*)//下一個偏移量為4(滿足規(guī)則2)是i2=4 的整數(shù)倍

int i3 = sizeof(char);//下一個偏移量為8(滿足規(guī)則2)是i=1 的整數(shù)倍

int i4 = sizeof(double);//下一個偏移量為9(不滿足規(guī)則1)不能被 i4 = 8所整除,所以應(yīng)當(dāng)9+7 = 16

所以總數(shù)為16+i4(8)= 24(滿足條件3)

所以為24

是否已經(jīng)明白呢?

不凡再看以下代碼

struct MyStruct 
{
   char dda;

//偏移量為0,滿足對齊方式,dda占用1個字節(jié);   double dda1; 

//下一個可用的地址的偏移量為1,不是sizeof(double)=8
//的倍數(shù),需要補足7個字節(jié)才能使偏移量變?yōu)?(滿足對齊
 //方式),因此VC自動填充7個字節(jié),dda1存放在偏移量為8
 //的地址上,它占用8個字節(jié)。   int type; 

//下一個可用的地址的偏移量為16,是sizeof(int)=4的倍
//數(shù),滿足int的對齊方式,所以不需要VC自動填充,type存
//放在偏移量為16的地址上,它占用4個字節(jié)。

};

//所有成員變量都分配了空間,空間總的大小為1+7+8+4=20,不是結(jié)構(gòu)
//的節(jié)邊界數(shù)(即結(jié)構(gòu)中占用最大空間的類型所占用的字節(jié)數(shù)sizeof
//(double)=8)的倍數(shù),所以需要填充4個字節(jié),以滿足結(jié)構(gòu)的大小為
//sizeof(double)=8的倍數(shù)。

 其中要是不想遵循結(jié)構(gòu)體對齊策略也可以用 #pragma pack 去掉內(nèi)存對齊,去掉的話,應(yīng)該會影響到效率吧。萬一在嵌入式下的話,有可能導(dǎo)致程序出錯。

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
結(jié)構(gòu)體(含位域)的sizeof
你會用sizeof嗎?(vc篇)
簡要講述C/C++中的操作符sizeof()
計算結(jié)構(gòu)體的大小
C++ 自定義結(jié)構(gòu)體和類 內(nèi)存對齊
sizeof用法總結(jié)(個人感覺非常好的一篇文章)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服