?
本文檔使用 PHP中文網(wǎng)手冊 發(fā)布
C程序創(chuàng)建,銷毀,訪問和操作對象。
C中的對象是執(zhí)行環(huán)境中的數(shù)據(jù)存儲區(qū)域,其內(nèi)容可以表示值(當(dāng)解釋為具有特定類型時,值是對象內(nèi)容的含義)。
每個對象都有。
大小(可以用sizeof來確定)
對齊要求(可以通過alignof來確定)(因為C11)
存儲時間(自動,靜態(tài),分配,線程本地)
壽命(等于存儲時間或臨時)
有效的類型(見下文)
價值(可能是不確定的)
可選地,表示該對象的標(biāo)識符
對象由聲明,分配函數(shù),字符串文字,復(fù)合文字以及通過返回具有數(shù)組成員的結(jié)構(gòu)或聯(lián)合的非左值表達(dá)式創(chuàng)建。
除了位字段,對象由一個或多個字節(jié)的連續(xù)序列組成,每個字節(jié)由CHAR_BIT
位組成,可以復(fù)制memcpy
到一個類型的對象中unsigned char[n]
,其中n
對象的大小就是這樣。結(jié)果數(shù)組的內(nèi)容被稱為對象表示。
如果兩個對象具有相同的對象表示形式,則它們會相等(除非它們是浮點型NaN)。相反的情況并非如此:比較相等的兩個對象可能具有不同的對象表示,因為對象表示的每一位都不需要參與該值。這些位可用于填充以滿足對齊要求,用于奇偶校驗,指示陷印表示等。
如果對象表示不表示對象類型的任何值,則稱為陷阱表示。除了通過字符類型的左值表達(dá)式讀取陷阱表達(dá)以外的任何其他方式都是未定義的行為。即使任何特定的成員是一個結(jié)構(gòu)或聯(lián)合的價值,也不是陷阱表示。
對于類型為char,signed char和unsigned char的對象,要求對象表示的每一位參與值表示,并且每個可能的位模式表示不同的值(不允許填充,陷阱位或多個表示形式)。
每個對象都有一個有效的類型,它確定哪些左值訪問是有效的,哪些違反了嚴(yán)格的別名規(guī)則。
如果對象是由聲明創(chuàng)建的,則該對象的聲明類型是對象的有效類型。
如果對象是由分配函數(shù)(包括realloc
)創(chuàng)建的,則它沒有聲明類型。這樣的對象獲得如下有效類型:
第一次通過一個左值寫入該對象,該左值的類型不是字符類型,此時該左值的類型變?yōu)樵搶ο蟮脑搶懭氲?em style="font-style: italic;">有效類型以及所有后續(xù)讀取。
memcpy
或者memmove
將另一個對象復(fù)制到該對象中,此時源對象的有效類型(如果有的話)成為該對象的有效類型以及所有后續(xù)讀取。
對沒有聲明類型的對象進(jìn)行任何其他訪問,有效類型是用于訪問的左值的類型。
給定一個有效類型為 T1 的對象,使用不同類型T2的左值表達(dá)式(通常是解引用指針)是未定義的行為,除非:
T2和T1是兼容的類型。
T2是與T1兼容的類型的cvr限定版本。
T2是與T1兼容的類型的有符號或無符號版本。
T2是一種聚合類型或聯(lián)合類型類型,其成員之一包括上述類型之一(包括遞歸地,子聚合的成員或包含的聯(lián)合)。
T2是一種字符類型(char,signed char或unsigned char)。
int i = 7;char* pc = (char*)(&i);if(pc[0] == '\x7') // aliasing through char is ok puts("This system is little-endian");else puts("This system is big-endian"); float* pf = (float*)(&i);float d = *pf; // UB: float lvalue *p cannot be used to access int
請注意,也可以通過聯(lián)合的非活動成員執(zhí)行類型雙關(guān)。
每個完整的對象類型都有一個稱為對齊需求的屬性,它是一個類型的整數(shù)值,size_t
表示可以分配此類對象的連續(xù)地址之間的字節(jié)數(shù)。有效的對齊值是兩個非負(fù)整數(shù)冪。
The alignment requirement of a type can be queried with alignof. | (since C11) |
---|
為了滿足結(jié)構(gòu)中所有成員的對齊要求,可以在其一些成員之后插入填充。
#include <stdio.h>#include <stdalign.h> // objects of struct S can be allocated at any address// because both S.a and S.b can be allocated at any addressstruct S { char a; // size: 1, alignment: 1 char b; // size: 1, alignment: 1}; // size: 2, alignment: 1 // objects of struct X must be allocated at 4-byte boundaries// because X.n must be allocated at 4-byte boundaries// because int's alignment requirement is (usually) 4struct X { int n; // size: 4, alignment: 4 char c; // size: 1, alignment: 1 // three bytes padding}; // size: 8, alignment: 4 int main(void){ printf("sizeof(struct S) = %zu\n", sizeof(struct S)); printf("alignof(struct S) = %zu\n", alignof(struct S)); printf("sizeof(struct X) = %zu\n", sizeof(struct X)); printf("alignof(struct X) = %zu\n", alignof(struct X));}
可能的輸出:
sizeof(struct S) = 2alignof(struct S) = 1sizeof(struct X) = 8alignof(struct X) = 4
每種對象類型都對該類型的每個對象強加對齊要求。任何類型最嚴(yán)格的(最大的)基本對齊方式都是對齊max_align_t
。最弱(最小)的對準(zhǔn)是種類的排列char
,signed char
以及unsigned char
,和等于1。
如果使用alignas將對象的對齊更嚴(yán)格(大于)max_align_t,則它具有擴展的對齊要求。其成員具有擴展對齊的結(jié)構(gòu)或聯(lián)合類型是超對齊類型。如果支持過度對齊類型,它是實現(xiàn)定義的,并且它們的支持在每種存儲持續(xù)時間中可能不同。 | (自C11以來) |
---|