495-51-60
51.如何向接受結(jié)構(gòu)參數(shù)的函數(shù)傳入常量值?怎樣創(chuàng)建無名的中間的常量的結(jié)構(gòu)值?
答:傳統(tǒng)的C語言沒有辦法生成匿名的結(jié)構(gòu)值。你必須使用臨時(shí)結(jié)構(gòu)或一個(gè)小的結(jié)構(gòu)生成函數(shù)。
C99標(biāo)準(zhǔn)引入了“復(fù)合字面量”,復(fù)合字面量的一種形式就可以允許結(jié)構(gòu)常量。例如,向假定的plotpoint函數(shù)傳入一個(gè)坐標(biāo)對(duì)常量,可以調(diào)用
plotpoint ((struct point)(1, 2));
與“指定初始值”結(jié)合,也可以用成員名稱確定成員值:
plotpoint ((struct point)(x = 1, y = 2));
52.怎樣從/向數(shù)據(jù)文件讀/寫結(jié)構(gòu)
答:用fwrite()編寫一個(gè)結(jié)構(gòu)相對(duì)簡(jiǎn)單:
fwrite(&somestruct, sizeof somestruct, 1, fp);
對(duì)應(yīng)的fread調(diào)用可以再把它讀回來,此處fwrite收到一個(gè)結(jié)構(gòu)的指針并把這個(gè)結(jié)構(gòu)的內(nèi)存映像作為字節(jié)流寫入文件(或在對(duì)應(yīng)的fread的時(shí)候讀入)。sizeof操作符計(jì)算出結(jié)構(gòu)占用的字節(jié)數(shù)。
只要范圍內(nèi)有fwrite的原型(通常只需包含<STDIO.H>),那么ANSI編譯器下這樣調(diào)用fwrite就是正確的,在ANSI之前的編譯器中,需要對(duì)第一個(gè)參數(shù)進(jìn)行類型轉(zhuǎn)換:
fwrite((char *)somestruct, sizeof somestruct, 1, fp);
重要的是fwrite接受字節(jié)指針,而不是結(jié)構(gòu)指針。
但是這樣用內(nèi)存映像寫出的書奴文件卻不能移植,尤其是當(dāng)結(jié)構(gòu)中包含浮點(diǎn)成員或指針的時(shí)候,結(jié)構(gòu)的內(nèi)存布局跟機(jī)器和編譯器都有關(guān),不同的編譯器可能使用不同數(shù)量的填充位,不同機(jī)器上基本類型的大小和字節(jié)順序也不盡相同,因此,作為內(nèi)存映像寫出的結(jié)構(gòu)在別的機(jī)器上(甚至是被別的編譯器編譯后)不一定能被讀回來,當(dāng)你需要在不同的機(jī)器上交換數(shù)據(jù)文件的時(shí)候,尤其要注意。
53.結(jié)構(gòu)充填
為什么我的編譯器在結(jié)構(gòu)中留下了空洞?這導(dǎo)致空間浪費(fèi)而且無法與外部數(shù)據(jù)文件進(jìn)行“二進(jìn)制”讀寫。能否關(guān)掉充填,或者控制結(jié)構(gòu)域的對(duì)齊方式?
答:當(dāng)內(nèi)存中的值合理對(duì)齊時(shí),很多機(jī)器都能非常高效地訪問。例如,在按字節(jié)尋址的機(jī)器中,2字節(jié)的short int型變量必須放在偶地址上,而4字節(jié)的long int型變量則必須存放在4的整數(shù)倍地址上。某些機(jī)器甚至根本就不能訪問沒有對(duì)齊的地址,因此必須要求所有的數(shù)據(jù)都正確地對(duì)齊
假如你聲明了這個(gè)結(jié)構(gòu):
struct
{
char c;
int i;
};
編譯器通常都會(huì)在char和int之間留出一個(gè)沒有命名也沒有使用的空洞,以確保int型域正確對(duì)齊。(根據(jù)最保守的對(duì)齊要求,結(jié)構(gòu)本身也是對(duì)齊的,因此第二個(gè)域可以根據(jù)第一個(gè)域的位置進(jìn)行累進(jìn)對(duì)齊,編譯器保證它所分配的結(jié)構(gòu)對(duì)齊,對(duì)malloc也是如此)
編譯器可能提供某種擴(kuò)展用于控制結(jié)構(gòu)的填充
如果你真的那么在意被浪費(fèi)的空間,可以把結(jié)構(gòu)中的域按從大到小的順序排列,以最大限度地降低充填的影響,數(shù)組成員應(yīng)該根據(jù)它的元素類型大小而不是整個(gè)數(shù)組的大小進(jìn)行排序的時(shí)候,使用位域也可以很好地控制大小和對(duì)齊,但是這樣也有它的缺點(diǎn)。
3.為什么sizeof返回的值大于結(jié)構(gòu)大小的期望值,是不是尾部有充填
答:為了確保分配連續(xù)的結(jié)構(gòu)數(shù)組時(shí)正確對(duì)齊,結(jié)構(gòu)可能有這種尾部