32位和64位系統下 int、char、long、double所占的內存以及內存字節對齊問題
8字節為上限
C類型 | 30位機器(字節) | 64位機器(字節) |
char | 1 | 1 |
short | 2 | 2 |
int | 4 | 4 |
long int | 4 | 8 |
long long | 8 | 8 |
char * | 4 | 8 |
float | 4 | 4 |
double | 8 | 8 |
#include<stdio.h> struct A { int a; char b; double c; char d; }; struct B { char a; double b; char c; }; int main() { printf("int =%lu,char=%lu,double=%lu\n",sizeof(int),sizeof(char),sizeof(double)); printf("structA=%lu structB=%lu\n",sizeof(struct A),sizeof(struct B)); return 0; } //64位 最多可以8位字節對齊 (先4位,遇8位變8位對齊) //32位 最多可以4位字節對齊
//64位編譯輸出: int =4,char=1,double=8 structA=24 structB=24 // structA: 4+(1+3)+8+(1+7) = 24 // structB: (1+7)+8+(1+7) = 24 //未遇到8位數據類型時時4字節對齊,遇到8字節數據類型變為8字節對齊 //32位編譯輸出: int =4,char=1,double=8 structA=20 structB=16 // struct A : 4+(1+3)+8+(1+3) = 20 // struct B : (1+3)+8+(1+3) = 16
//不管怎么樣都只能是4字節對齊
結構體字節對齊問題:
未進行特殊說明時,按照結構體中size最大成員對齊
當進行對應字節對齊說明后,按照說明要求字節對齊
阿秀筆記:
c++11以后引入兩個關鍵字 alignas與 alignof。其中 alignof 可以計算出類型的對齊方式, alignas 可以指定結構體的對齊方式。
但是 alignas 在某些情況下是不能使用的,具體見下面的例子
// alignas 生效的情況 struct Info { uint8_t a; uint16_t b; uint8_t c; }; std::cout << sizeof(Info) << std::endl; // 6 2 + 2 + 2 std::cout << alignof(Info) << std::endl; // 2 struct alignas(4) Info2 { uint8_t a; uint16_t b; uint8_t c; }; std::cout << sizeof(Info2) << std::endl; // 8 4 + 4 std::cout << alignof(Info2) << std::endl; // 4
//☄ alignas 將內存對齊調整為4個字節。所以 sizeof(Info2) 的值變為了8
// alignas 失效的情況 struct Info { uint8_t a; uint32_t b; uint8_t c; }; std::cout << sizeof(Info) << std::endl; // 12 4 + 4 + 4 std::cout << alignof(Info) << std::endl; // 4 struct alignas(2) Info2 { uint8_t a; uint32_t b; uint8_t c; }; std::cout << sizeof(Info2) << std::endl; // 12 4 + 4 + 4 std::cout << alignof(Info2) << std::endl; // 4
//☄ 若 alignas 小於自然對齊的最小單位,則被忽略。
☄ 如果想使用單字節對齊的方式,使用 alignas 是無效的。應該使用 #pragma pack(push,1) 或者使用__attribute__((packed)) 。
#if defined(__GNUC__) || defined(__GNUG__) #define ONEBYTE_ALIGN __attribute__((packed)) #elif defined(_MSC_VER) #define ONEBYTE_ALIGN #pragma pack(push,1) #endif struct Info { uint8_t a; uint32_t b; uint8_t c; } ONEBYTE_ALIGN; #if defined(__GNUC__) || defined(__GNUG__) #undef ONEBYTE_ALIGN #elif defined(_MSC_VER) #pragma pack(pop) #undef ONEBYTE_ALIGN #endif std::cout << sizeof(Info) << std::endl; // 6 1 + 4 + 1 std::cout << alignof(Info) << std::endl; // 6
☄ 確定結構體中每個元素大小可以通過下面這種方法:
#if defined(__GNUC__) || defined(__GNUG__) #define ONEBYTE_ALIGN __attribute__((packed)) #elif defined(_MSC_VER) #define ONEBYTE_ALIGN #pragma pack(push,1) #endif /** * 0 1 3 6 8 9 15 * +-+---+-----+---+-+-------------+ * | | | | | | | * |a| b | c | d |e| pad | * | | | | | | | * +-+---+-----+---+-+-------------+ */ struct Info { uint16_t a : 1; uint16_t b : 2; uint16_t c : 3; uint16_t d : 2; uint16_t e : 1; uint16_t pad : 7; } ONEBYTE_ALIGN; #if defined(__GNUC__) || defined(__GNUG__) #undef ONEBYTE_ALIGN #elif defined(_MSC_VER) #pragma pack(pop) #undef ONEBYTE_ALIGN #endif std::cout << sizeof(Info) << std::endl; // 2 std::cout << alignof(Info) << std::endl; // 1