02_32位和64位系統下 int、char、long、double所占的內存以及內存字節對齊問題


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

 


    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM