1. 程式人生 > >union, enum, and struct, 以及結構填充和位字段實現。

union, enum, and struct, 以及結構填充和位字段實現。

表示 bits 聯合 follow ++ alignment necessary only lds

Table 4-9 Compiler storage of data objects by byte alignment

TypeBytesAlignment
char, bool, _Bool 1 Located at any byte address.
short, wchar_t 2 Located at any address that is evenly divisible by 2.
float, int, long, pointer 4 Located at an address that is evenly divisible by 4.
long long, double, long double 8 Located at an address that is evenly divisible by 8.

Unions

當使用不同類型的成員訪問聯合成員時,可以從原始類型的表示中預測結果值。沒有錯誤。

Enumerations

枚舉類型的一個對象是最小的整數類型包含枚舉的範圍內實現。

在C和C++中的模式,模式沒有-- enum_is_int,如果枚舉包含積極的枚舉值,該枚舉的存儲類型是從下面的列表中的第一個符號類型,根據該枚舉器枚舉的範圍。在其他模式,在這種情況下,一個枚舉包含任何負面的枚舉值,該枚舉的存儲類型是下列第一,根據該枚舉數的範圍在枚舉:

  • unsigned char if not using --enum_is_int
  • signed char if not using --enum_is_int
  • unsigned short if not using --enum_is_int
  • signed short if not using --enum_is_int
  • signed int
  • unsigned int except C with --strict
  • signed long long except C with --strict
  • unsigned long long
    except C with --strict.

在混合使用和不使用-enum_is_int選項編譯的轉換單元以及共享接口或數據結構時,必須註意。在嚴格C中,枚舉數值必須表示為INT。也就是說,他們必須在範圍內-2147483648到2147483647,包括在內。對超出範圍的枚舉數值發出警告:

#66: enumeration value is out of "int" range

Structures

結構可以包含填充,以確保字段正確對齊,並確保結構本身正確地對齊。下圖顯示了一個常規的、不打包的結構的示例。填充字節1、2和3以確保正確的字段對齊。填充字節11和12以確保正確的結構對齊。函數返回結構的大小,包括填充。

技術分享圖片

編譯器根據結構的定義方式以下列方式之一對結構進行解析:

  • 定義為靜態或外部結構的結構用零填充。
  • 堆棧或堆上的結構,如使用malloc()或AUTO定義的結構,將填充以前存儲在這些內存位置中的內容。您不能使用memcmp()來比較以這種方式定義的填充結構。

Bitfields

在非打包結構中,ARM編譯器在容器中分配位字段。容器是聲明類型的對齊對象。分配Bitfield使指定的第一個字段占用單詞中尋址最低的位,具體取決於配置:

小端(Little-endian):最低地址意味著最不重要。大端(Big-endian):最低地址意味著最重要。

在嚴格的1990 ISO標準C中,唯一允許使用位字段的類型是int、符號int和無符號int。對於非int位字段,編譯器將顯示一個錯誤。無符號或無符號限定符聲明的普通位字段被視為無符號。例如,intx:10分配一個10位的無符號整數。位字段被分配給具有足夠數量未分配位的正確類型的第一個容器,例如:

struct X
{
    int x:10;
    int y:20;
};

第一個聲明創建一個整數容器,並將10位分配給x。在第二個聲明中,編譯器找到具有足夠數量未分配位的現有整數容器,並在與x相同的容器中分配y。

位字段完全包含在其容器中。不適合於容器的位字段放置在相同類型的下一個容器中。例如,如果為結構聲明了額外的位字段,則z的聲明會溢出容器:

struct X
{
    int x:10;
    int y:20;
    int z:5;
};

編譯器為第一個容器分配剩余的兩位,並為z分配一個新的整數容器。Bitfield容器可以相互重疊,例如:

struct X
{
    int x:10;
    char y:2;
};

第一個聲明創建一個整數容器,並將10位分配給x。這10位占用整數容器的第一個字節和第二個字節的兩個位。在第二個聲明中,編譯器檢查char類型的容器。沒有合適的容器,因此編譯器分配一個新的正確對齊的char容器。

由於CHAR的自然對齊是1,編譯器會搜索包含足夠數量未分配位的第一個字節,以完全包含位字段。在示例結構中,int容器的第二字節具有分配給x的兩個比特,以及未分配的六個比特。編譯器在前一個int容器的第二個字節開始分配一個字符容器,跳過分配給x的前兩個位,並將兩個位分配給y。

如果y被聲明為char y:8,編譯器會將第二個字節存儲起來,並將一個新的char容器分配給第三個字節,因為位字段不能溢出它的容器。下圖顯示了以下示例結構的位字段分配:

struct X
{
    int x:10;
    char y:8;
};

技術分享圖片

相同的基本規則適用於具有不同容器類型的位字段聲明。例如,向示例結構中添加int位字段會提供:

struct X
{
    int x:10;
    char y:8;
    int z:5;
}
The compiler allocates an int container starting at the same location as the int x:10 container and allocates a byte-aligned char and 5-bit bitfield, as follows: Figure 10-3 Bitfield allocation 2 技術分享圖片
You can explicitly pad a bitfield container by declaring an unnamed bitfield of size zero. A bitfield of zero size fills the container up to the end if the container is not empty. A subsequent bitfield declaration starts a new empty container.

Note

As an optimization, the compiler might overwrite padding bits in a container with unspecified values when a bitfield is written. This does not affect normal usage of bitfields.

Bitfields in packed structures

Packed bitfield containers, including all bitfield containers in packed structures, have an alignment of 1. Therefore the maximum bit padding inserted to align a packed bitfield container is 7 bits. For an unpacked bitfield container, the maximum bit padding is 8*sizeof(container-type)-1 bits. Tail-padding is always inserted into the structure as necessary to ensure arrays of the structure will have their elements correctly aligned. A packed bitfield container is only large enough (in bytes) to hold the bitfield that declared it. Non-packed bitfield containers are the size of their type. The following examples illustrate these interactions.
struct A {          int z:17; }; // sizeof(A) = 4, alignment = 4
struct A { __packed int z:17; }; // sizeof(A) = 3, alignment = 1
__packed struct A { int z:17; }; // sizeof(A) = 3, alignment = 1
struct A { char y:1;          int z:31; }; // sizeof(A) = 4, alignment = 4
struct A { char y:1; __packed int z:31; }; // sizeof(A) = 4, alignment = 1
__packed struct A { char y:1; int z:31; }; // sizeof(A) = 4, alignment = 1
struct A { char y:1;          int z:32; }; // sizeof(A) = 8, alignment = 4
struct A { char y:1; __packed int z:32; }; // sizeof(A) = 5, alignment = 1
__packed struct A { char y:1; int z:32; }; // sizeof(A) = 5, alignment = 1
struct A { int x; char y:1;          int z:31; };  // sizeof(A) = 8, alignment = 4
struct A { int x; char y:1; __packed int z:31; };  // sizeof(A) = 8, alignment = 4
__packed struct A { int x; char y:1; int z:31; };  // sizeof(A) = 8, alignment = 1
struct A { int x; char y:1;          int z:32; };  // sizeof(A) = 12, alignment = 4 [1]
struct A { int x; char y:1; __packed int z:32; };  // sizeof(A) = 12, alignment = 4 [2]
__packed struct A { int x; char y:1; int z:32; };  // sizeof(A) = 9, alignment = 1
Note that [1] and [2] are not identical; the location of z within the structure and the tail-padding differ.
struct example1
{
int a : 8;  /* 4-byte container at offset 0 */
__packed int b : 8;  /* 1-byte container at offset 1 */
__packed int c : 24; /* 3-byte container at offset 2 */
}; /* Total size 8 (3 bytes tail padding) */;
struct example2
{
__packed int a : 8; /* 1-byte container at offset 0 */
__packed int b : 8; /* 1-byte container at offset 1 */
int c : 8; /* 4-byte container at offset 0 */
}; /* Total size 4 (No tail padding) */
struct example3
{
int a : 8;  /* 4-byte container at offset 0 */
__packed int b : 32; /* 4-byte container at offset 1 */
__packed int c : 32; /* 4-byte container at offset 5 */
int d : 16; /* 4-byte container at offset 8 */
int e : 16; /* 4-byte container at offset 12 */
int f : 16; /* In previous container */
}; /* Total size 16 (No tail padding) */

union, enum, and struct, 以及結構填充和位字段實現。