小議大小端模式對(duì)C語言的共用體結(jié)構(gòu)的影響
1、一些問題
問題1
- #include "stdio.h"
- union
- {
- int i;
- char ch[2];
- }key;
- main()
- {
- key.i=65*256+66;
- printf("%c\t%c\n",key.ch[0],key.ch[1]);
- }
答案是B A,;為什么不是A B呢,?
在前面的文章中我們已經(jīng)測(cè)試過,X86體系結(jié)構(gòu)的CPU是小端模式的,。比如一個(gè)數(shù)0x1234,放在內(nèi)存里按照內(nèi)存地址從低往高實(shí)際上是低地址字節(jié)里放的是0x34,,高字節(jié)里放的是0x12。小端模式和我們平時(shí)感覺上的一致,,把數(shù)位數(shù)越高的部分放在地址越高的部分,。union類型是共享內(nèi)存的,union中是按照從低到高放的,,i=0x4142,,也就是低地址中放的是42,高地址中放的是41,,按照ch[0],ch[1]的順序輸出就是B
A,。如果是大端模式的話就是打印兩個(gè)空了,故不會(huì)出現(xiàn)A B的情況,。
問題2
- union myun
- {
- struct { int x; int y; int z; }u;
- int k;
- }a;
- int main()
- {
- a.u.x =4;
- a.u.y =5;
- a.u.z =6;
- a.k = 0;
- printf("%d %d %d\n",a.u.x,a.u.y,a.u.z);
- return 0;
- }
union類型是共享內(nèi)存的,,以size最大的結(jié)構(gòu)作為自己的大小,這樣的話,,myun這個(gè)結(jié)構(gòu)就包含u這個(gè)結(jié)構(gòu)體,,而大小也等于u這個(gè)結(jié)構(gòu)體的大小,在內(nèi)存中的排列為聲明的順序x,y,z從低到高,,然后賦值的時(shí)候,,在內(nèi)存中,就是x的位置放置4,,y的位置放置5,,z的位置放置6,現(xiàn)在對(duì)k賦值,,對(duì)k的賦值因?yàn)槭莡nion,,要共享內(nèi)存,,所以從union的首地址開始放置,首地址開始的位置其實(shí)是x的位置,,這樣原來內(nèi)存中x的位置就被k所賦的值代替了,,就變?yōu)?了,這個(gè)時(shí)候要進(jìn)行打印,,就直接看內(nèi)存里就行了,,x的位置也就是k的位置是0,而y,,z的位置的值沒有改變,,所以應(yīng)該是0,5,6。
問題3
- int checkCPU()
- {
- union
- {
- int a;
- char b;
- }c;
- c.a = 1;
- return (c.b == 1); // 小端返回TRUE,大端返回FALSE
- }
這個(gè)就不詳細(xì)解釋了,,用來判定CPU大小端模式的一個(gè)經(jīng)典例子,。
問題4
- union {
- int a[2];
- long b;
- char c[4];
- }s;
- main()
- {
- s.a[0]=0x12345678;
- s.a[1]=0x23456789;
- printf("%lx\n",s.b);
- printf("%x,%x,%x,%x\n",s.c[0],s.c[1],s.c[2],s.c[3]);
- }
答案是:
12345678
78,56,34,12
問題5
- # include <stdio.h>
- main()
- {
- union {
- long i;
- int k;
- char ii;
- char s[4];
- } mix ;
- mix.k=0x23456789;
- printf("mix.i=%lx\n",mix.i);
- printf("mix.k=%x\n",mix.k);
- printf("mix.ii=%x\n",mix.ii);
- printf("mix.s[0]=%x\tmix.s[1]=%x\n",mix.s[0],mix.s[1]);
- printf("mix.s[2]=%x\tmix.s[3]=%x\n",mix.s[2],mix.s[3]);
- return 0;
- }
答案是:
mix.i=23456789
mix.k=23456789
mix.ii=ffffff89
mix.s[0]=ffffff89 mix.s[1]=67
mix.s[2]=45 mix.s[3]=23
出現(xiàn)f是因?yàn)榘裞har型強(qiáng)制轉(zhuǎn)換成int型輸出,0x89最高位1000 1001最高位為1,,轉(zhuǎn)換為int類型的時(shí)候認(rèn)為是負(fù)數(shù),,而且數(shù)在計(jì)算機(jī)中是按補(bǔ)碼存儲(chǔ)的,所以自然高位補(bǔ)1了,。
2,、這是一個(gè)什么問題
2.1、共用體結(jié)構(gòu)的意義
問題:
假設(shè)網(wǎng)絡(luò)節(jié)點(diǎn)A 和網(wǎng)絡(luò)節(jié)點(diǎn)B 中的通信協(xié)議涉及四類報(bào)文,,報(bào)文格式為“報(bào)文類型字段+報(bào)文內(nèi)容的結(jié)構(gòu)體”,四個(gè)報(bào)文內(nèi)容的結(jié)構(gòu)體類型分別為STRUCTTYPE1~ STRUCTTYPE4,,如何編寫程序以最簡(jiǎn)單的方式組
織一個(gè)統(tǒng)一的報(bào)文數(shù)據(jù)結(jié)構(gòu),。
分析:
報(bào)文的格式為“報(bào)文類型+報(bào)文內(nèi)容的結(jié)構(gòu)體”,在真實(shí)的通信中,,每次只能發(fā)四類報(bào)文中的一種,,我們可以將四類報(bào)文的結(jié)構(gòu)體組織為一個(gè)union(共享一段內(nèi)存,但每次有效的只是一種),,然后和報(bào)文類型字段統(tǒng)一組織成一個(gè)報(bào)文數(shù)據(jù)結(jié)構(gòu),。
解答:
- typedef unsigned char BYTE;
- //報(bào)文內(nèi)容聯(lián)合體
- typedef union tagPacketContent
- {
- STRUCTTYPE1 pkt1;
- STRUCTTYPE2 pkt2;
- STRUCTTYPE3 pkt1;
- STRUCTTYPE4 pkt2;
- }PacketContent;
- //統(tǒng)一的報(bào)文數(shù)據(jù)結(jié)構(gòu)
- typedef struct tagPacket
- {
- BYTE pktType;
- PacketContent pktContent;
- }Packet;
當(dāng)多個(gè)基本數(shù)據(jù)類型或復(fù)合數(shù)據(jù)結(jié)構(gòu)要占用同一片內(nèi)存時(shí),我們要使用共用體,;當(dāng)多種類型,,多個(gè)對(duì)象,多個(gè)事物只取其一時(shí)(我們姑且通俗地稱其為“n 選1”),,我們也可以使用共用體來發(fā)揮其長(zhǎng)處,。把幾種不同類型的變量放到同一段內(nèi)存單元中,這些變量在內(nèi)存中占用的字節(jié)數(shù)可能不同,,但都從同一個(gè)地址開始存放,。也就是使用覆蓋技術(shù),,幾個(gè)變量互相覆蓋。同一個(gè)內(nèi)存段可以用來存放幾種不同類型的成員,,但在每一瞬間只能存放其中一種,,而不能同時(shí)存放幾種。即,,每一瞬間只有一個(gè)成員起作用,,其他的成員不起作用,不能同時(shí)存在和起作用,。共用體變量中起作用的成員是最后一次存放的成員,,在存入一個(gè)新的成員后原有的成員就失去了作用。
2.2,、大小端模式對(duì)共用體的影響
當(dāng)共用體中有不同類型的變量,,用一種變量類型給共用體賦值,但用另一種變量類型讀取共用體的時(shí)候就涉及到大小端的問題,。比如在問題1中,,給int類型的變量i賦值,但通過char類型的數(shù)組來讀取時(shí),,就要注意字節(jié)序的問題,,也就是大小端的問題。
|