1. 程式人生 > >C/C++基本型別佔用記憶體總結

C/C++基本型別佔用記憶體總結

C / C ++型別佔用記憶體總結

ç語言

Ç程式碼32位註釋

/*************************************************************************
    > Description: ubuntu32位GCC4.8.4下面各變數型別大小
 ************************************************************************/

#include <stdio.h>
#include <string.h>

enum color {
    BLACK = 0
, YELLOW = 1, WHITE, BLUE }; //4 Byte /* * 位元組對齊原則: * 1.資料型別自身的對齊值:對於char型資料,為1;對於short型,為2,對於int,float型,為4;double型別,為8,單位位元組 * 2.結構體或者類的自身對齊值:其成員中自身對齊值最大的那個值 * 3.指定對齊值:#pragma pack (value)時的指定對齊值value。 * 4.資料成員、結構體和類的有效對齊值:自身對齊值和指定對齊值中小的那個值 * 注意:32位GCC預設指定對齊為4位元組,64位GCC預設指定對齊為8位元組 * VS2010不管是32位還是64位編譯器,其預設指定對齊值為結構體或者類的自身對齊值(成員中自身對齊值最大的值) */
struct person8 { char gender; //佔用2位元組,自身1位元組 short age; //佔用2位元組 char party; //佔用4位元組,自身1位元組 int height; //佔用4位元組 char name[5]; //佔用8位元組,自身5位元組 double weight; //佔用8位元組 char addr; //佔用4位元組,自身1位元組 }; //32 Byte 有效對齊值4 struct person4 { char gender; //佔用2位元組,自身1位元組
short age; //佔用2位元組 char party; //佔用4位元組,自身1位元組 int height; //佔用4位元組 }; //12 Byte 有效對齊值4 struct person2 { char gender; //佔用2位元組,自身1位元組 short age; //佔用2位元組 char party; //佔用2位元組,自身1位元組 }; //6 Byte 有效對齊值2 struct person1 { char gender; //佔用1位元組,自身1位元組 }; //1 Byte 有效對齊值1 /* * #pragma pack(1/2/4/8)修改指定對齊位元組數 * 注意:修改並不一定能奏效,因為還要看結構中成員最大那個對齊值 * 成員最大對齊值超過指定對齊值,指定才能起作用 */ #pragma pack(2) struct Pragma_2 { int a; //4 char b; //2 double c; //8 char d; //2 }; //16 Byte 有效對齊值2 #pragma pack(1) struct Pragma_1 { char a; //1 double b; //8 char c; //1 }; //10 Byte 有效對齊值1 #pragma pack() typedef struct IP { unsigned char szIP1; //high unsigned char szIP2; unsigned char szIP3; unsigned char szIP4; }IP_INT; typedef union IP_addr { IP_INT ip_int; int ipv4; char type; }IP_ADDR; //4 Byte static double function(int a, float b) { return 0; } int main(void) { char szchar = 65; //1位元組 unsigned char uszchar = 95; //1位元組 short sishort = -100; //2位元組 unsigned short usishort = 100; //2位元組 int iint = -200; //4位元組 unsigned int uiint= 200; //4位元組 float ffloat = -0.8; //4位元組 double ddouble = 99.99; //8位元組 long llong = 999; //4位元組 unsigned long ullong = 999; //4位元組 long long lllong = 9999; //8位元組 enum color color1; //4位元組 union IP_addr pc_ip; //4位元組 char* pchar; //4位元組 int* pint; //4位元組 long long* pllint; //4位元組 double* pdouble; //4位元組 double (*pffun)(int,float); //4位元組 /* * sizeof計算大小計算整個字串長度 * strlen計算截止到'\0'的字元長度 */ char str1[] = "12345\0678"; //str1字串加上結束符'\0'一共佔用8位元組,'\067'表示一個字元 char str2[] = "12345\\0678"; //str2字串加上結束符'\0'一共佔用11位元組,'\\'表示一個'\'字元 /* ArryNames是一個數組,故sizeof(ArryNames)大小為72位元組 */ char ArryNames[9][8] = {"Tom","Jerry","Ham","Jobs","","Benson","Nick","Evan","jiexue"}; /* names是一個指標陣列,故sizeof(names)大小為36位元組 */ const char* names[9] = {"Tom","Jerry","Ham","Jobs","","Benson","Nick","Evan","jiexue"}; printf(" ----------------------------- \n"); printf("****在%d位系統上,各型別佔用位元組數****\n", sizeof(void*) * 8); printf("**** GCC Version: %s ****\n", __VERSION__); printf(" ----------------------------- \n"); printf("-------------基本型別----------------\n"); printf("char: %d\n", sizeof(szchar)); printf("unsigned char: %d\n", sizeof(uszchar)); printf("short: %d\n", sizeof(sishort)); printf("unsigned short: %d\n", sizeof(usishort)); printf("int: %d\n", sizeof(iint)); printf("unsigned int: %d\n", sizeof(uiint)); printf("float: %d\n", sizeof(ffloat)); printf("double: %d\n", sizeof(ddouble)); printf("long: %d\n", sizeof(llong)); printf("unsigned long: %d\n", sizeof(ullong)); printf("long long: %d\n", sizeof(lllong)); printf("---------列舉、結構、聯合------------\n"); printf("enum: %d\n", sizeof(enum color)); printf("struct person8: %d\n", sizeof(struct person8)); printf("struct person4: %d\n", sizeof(struct person4)); printf("struct person2: %d\n", sizeof(struct person2)); printf("struct person1: %d\n", sizeof(struct person1)); printf("union IPV4: %d\n", sizeof(pc_ip)); printf("--------指標、函式、函式指標---------\n"); printf("char*: %d\n", sizeof(char*)); printf("int*: %d\n", sizeof(pint)); printf("long long*: %d\n", sizeof(pllint)); printf("double*: %d\n", sizeof(pdouble)); printf("main: %d\n", sizeof(main)); //標準C禁止這麼使用,GCC返回1,VS編譯不通過 printf("function: %d\n", sizeof(function)); //標準C禁止這麼使用,GCC返回1,VS編譯不通過 printf("&main: %d\n", sizeof(&main)); //返回4 printf("&function: %d\n", sizeof(&function)); //返回4 printf("main(): %d\n", sizeof(main())); //返回4 printf("function*: %d\n", sizeof(pffun)); printf("---------------字串----------------\n"); printf("str1[] = \"12345\\0678\": %d\n",strlen(str1)); printf("str1[] = \"12345\\0678\": %d\n", sizeof(str1)); printf("str2[] = \"12345\\\\0678\": %d\n",strlen(str2)); printf("str2[] = \"12345\\\\0678\": %d\n", sizeof(str2)); printf("char ArryNames[9][8]: %d\n", sizeof(ArryNames)); printf("char ArryNames[9][8]: %d\n", strlen(ArryNames[0])); //strlen(ArryNames)會給警告,得到的依然是3 printf("char* names[9]: %d\n", sizeof(names)); printf("------------修改對齊方式-------------\n"); printf("struct Pragma_2: %d\n", sizeof(struct Pragma_2)); printf("struct Pragma_1: %d\n", sizeof(struct Pragma_1)); getchar(); return 0; }

輸出

    -----------------------------    
****在32位系統上,各型別佔用位元組數****
****      GCC Version: 4.8.4     ****
    -----------------------------    
-------------基本型別----------------
char: 1
unsigned char: 1
short: 2
unsigned short: 2
int: 4
unsigned int: 4
float: 4
double: 8
long: 4
unsigned long: 4
long long: 8
---------列舉、結構、聯合------------
enum: 4
struct person8: 32
struct person4: 12
struct person2: 6
struct person1: 1
union IPV4: 4
--------指標、函式、函式指標---------
char*: 4
int*: 4
long long*: 4
double*: 4
main: 1
function: 1
&main: 4
&function: 4
main(): 4
function*: 4
---------------字串----------------
str1[] = "12345\0678": 7
str1[] = "12345\0678": 8
str2[] = "12345\\0678": 10
str2[] = "12345\\0678": 11
char ArryNames[9][8]: 72
char ArryNames[9][8]: 3
char* names[9]: 36
------------修改對齊方式-------------
struct Pragma_2: 16
struct Pragma_1: 10

Ç程式碼64位註釋

/*************************************************************************
    > Description: GCC4.2.1下面各變數型別大小
 ************************************************************************/

#include <stdio.h>
#include <string.h>

enum color {
    BLACK = 0,
    YELLOW = 1,
    WHITE,
    BLUE
};  //4 Byte

/*
 * 位元組對齊原則:
 *   1.資料型別自身的對齊值:對於char型資料,為1;對於short型,為2,對於int,float型,為4;double型別,為8,單位位元組
 *   2.結構體或者類的自身對齊值:其成員中自身對齊值最大的那個值
 *   3.指定對齊值:#pragma pack (value)時的指定對齊值value。
 *   4.資料成員、結構體和類的有效對齊值:自身對齊值和指定對齊值中小的那個值
 * 注意:32位GCC預設指定對齊為4位元組,64位GCC預設指定對齊為8位元組
 *     VS2010不管是32位還是64位編譯器,其預設指定對齊值為結構體或者類的自身對齊值(成員中自身對齊值最大的值)
 */
struct person8 {
    char gender;    //佔用2位元組,自身1位元組
    short age;      //佔用2位元組
    char party;     //佔用4位元組,自身1位元組
    int height;     //佔用4位元組
    char name[5];   //佔用12位元組,自身5位元組
    double weight;    //佔用8位元組
    char addr;      //佔用8位元組,自身1位元組
};  //40 Byte   有效對齊值8

struct person4 {
    char gender;    //佔用2位元組,自身1位元組
    short age;      //佔用2位元組
    char party;     //佔用4位元組,自身1位元組
    int height;     //佔用4位元組
};  //12 Byte   有效對齊值4

struct person2 {
    char gender;    //佔用2位元組,自身1位元組
    short age;      //佔用2位元組
    char party;     //佔用2位元組,自身1位元組
};  //6 Byte   有效對齊值2

struct person1 {
    char gender;    //佔用1位元組,自身1位元組
};  //1 Byte   有效對齊值1

/*
 * #pragma pack(1/2/4/8)修改指定對齊位元組數
 * 注意:修改並不一定能奏效,因為還要看結構中成員最大那個對齊值
 *      成員最大對齊值超過指定對齊值,指定才能起作用
 */
#pragma pack(2)
struct Pragma_2
{
    int   a;    //4
    char  b;    //2
    double c;   //8
    char  d;    //2
};  //16 Byte   有效對齊值2

#pragma pack(1)
struct Pragma_1
{
    char  a;    //1
    double b;   //8
    char  c;    //1
};  //10 Byte   有效對齊值1
#pragma pack()

typedef struct IP {
    unsigned char szIP1;    //high
    unsigned char szIP2;
    unsigned char szIP3;
    unsigned char szIP4;
}IP_INT;

typedef union IP_addr {
    IP_INT ip_int;
    int ipv4;
    char type;
}IP_ADDR;   //4 Byte

static double function(int a, float b)
{
    return 0;
}

int main(void)
{
    char szchar = 65;   //1位元組
    unsigned char uszchar = 95; //1位元組

    short sishort = -100;   //2位元組
    unsigned short usishort = 100;  //2位元組

    int iint = -200;    //4位元組
    unsigned int uiint= 200;    //4位元組

    float ffloat = -0.8;    //4位元組
    double ddouble = 99.99; //8位元組

    long llong = 999;   //8位元組
    unsigned long ullong = 999; //8位元組
    long long lllong = 9999;    //8位元組

    enum color color1;  //4位元組
    union IP_addr pc_ip;    //4位元組

    char* pchar;    //8位元組
    int* pint;  //8位元組
    long long* pllint;  //8位元組
    double* pdouble;    //8位元組

    double (*pffun)(int,float); //8位元組

    /*
     * sizeof計算大小計算整個字串長度
     * strlen計算截止到'\0'的字元長度
     */
    char str1[] = "12345\0678";     //str1字串加上結束符'\0'一共佔用8位元組,'\067'表示一個字元
    char str2[] = "12345\\0678";    //str2字串加上結束符'\0'一共佔用11位元組,'\\'表示一個'\'字元

    /* ArryNames是一個數組,故sizeof(ArryNames)大小為72位元組 */
    char ArryNames[9][8] = {"Tom","Jerry","Ham","Jobs","","Benson","Nick","Evan","jiexue"};
    /* names是一個指標陣列,故sizeof(names)大小為72位元組 */
    const char* names[9] = {"Tom","Jerry","Ham","Jobs","","Benson","Nick","Evan","jiexue"};

    printf("    -----------------------------    \n");
    printf("****在%d位系統上,各型別佔用位元組數****\n", sizeof(void*) * 8);
    printf("****      GCC Version: %s     ****\n", __VERSION__);
    printf("    -----------------------------    \n");
    printf("-------------基本型別----------------\n");
    printf("char: %d\n", sizeof(szchar));
    printf("unsigned char: %d\n", sizeof(uszchar));
    printf("short: %d\n", sizeof(sishort));
    printf("unsigned short: %d\n", sizeof(usishort));
    printf("int: %d\n", sizeof(iint));
    printf("unsigned int: %d\n", sizeof(uiint));
    printf("float: %d\n", sizeof(ffloat));
    printf("double: %d\n", sizeof(ddouble));
    printf("long: %d\n", sizeof(llong));
    printf("unsigned long: %d\n", sizeof(ullong));
    printf("long long: %d\n", sizeof(lllong));

    printf("---------列舉、結構、聯合------------\n");
    printf("enum: %d\n", sizeof(enum color));
    printf("struct person8: %d\n", sizeof(struct person8));
    printf("struct person4: %d\n", sizeof(struct person4));
    printf("struct person2: %d\n", sizeof(struct person2));
    printf("struct person1: %d\n", sizeof(struct person1));
    printf("union IPV4: %d\n", sizeof(pc_ip));

    printf("--------指標、函式、函式指標---------\n");
    printf("char*: %d\n", sizeof(char*));
    printf("int*: %d\n", sizeof(pint));
    printf("long long*: %d\n", sizeof(pllint));
    printf("double*: %d\n", sizeof(pdouble));
    printf("main: %d\n", sizeof(main)); //標準C禁止這麼使用,GCC返回1,VS編譯不通過
    printf("function: %d\n", sizeof(function)); //標準C禁止這麼使用,GCC返回1,VS編譯不通過
    printf("&main: %d\n", sizeof(&main)); //返回8
    printf("&function: %d\n", sizeof(&function));    //返回8
    printf("main(): %d\n", sizeof(main())); //返回4
    printf("function*: %d\n", sizeof(pffun));

    printf("---------------字串----------------\n");
    printf("str1[] = \"12345\\0678\": %d\n",strlen(str1));
    printf("str1[] = \"12345\\0678\": %d\n", sizeof(str1));
    printf("str2[] = \"12345\\\\0678\": %d\n",strlen(str2));
    printf("str2[] = \"12345\\\\0678\": %d\n", sizeof(str2));
    printf("char ArryNames[9][8]: %d\n", sizeof(ArryNames));
    printf("char ArryNames[9][8]: %d\n", strlen(ArryNames[0])); //strlen(ArryNames)會給警告,得到的依然是3
    printf("char* names[9]: %d\n", sizeof(names));

    printf("------------修改對齊方式-------------\n");
    printf("struct Pragma_2: %d\n", sizeof(struct Pragma_2));
    printf("struct Pragma_1: %d\n", sizeof(struct Pragma_1));

    getchar();

    return 0;
}

輸出

    -----------------------------    
****在64位系統上,各型別佔用位元組數****
****      GCC Version: 4.2.1     ****
    -----------------------------    
-------------基本型別----------------
char: 1
unsigned char: 1
short: 2
unsigned short: 2
int: 4
unsigned int: 4
float: 4
double: 8
long: 8
unsigned long: 8
long long: 8
---------列舉、結構、聯合------------
enum: 4
struct person8: 40
struct person4: 12
struct person2: 6
struct person1: 1
union IPV4: 4
--------指標、函式、函式指標---------
char*: 8
int*: 8
long long*: 8
double*: 8
main: 1
function: 1
&main: 8
&function: 8
main(): 4
function*: 8
---------------字串----------------
str1[] = "12345\0678": 7
str1[] = "12345\0678": 8
str2[] = "12345\\0678": 10
str2[] = "12345\\0678": 11
char ArryNames[9][8]: 72
char ArryNames[9][8]: 3
char* names[9]: 72
------------修改對齊方式-------------
struct Pragma_2: 16
struct Pragma_1: 10
    -----------------------------    
****在64位系統上,各型別佔用位元組數****
****      GCC Version: 6.3.0     ****
    -----------------------------    
-------------基本型別----------------
char: 1
unsigned char: 1
short: 2
unsigned short: 2
int: 4
unsigned int: 4
float: 4
double: 8
long: 8
unsigned long: 8
long long: 8
---------列舉、結構、聯合------------
enum: 4
struct person8: 40
struct person4: 12
struct person2: 6
struct person1: 1
union IPV4: 4
--------指標、函式、函式指標---------
char*: 8
int*: 8
long long*: 8
double*: 8
main: 1
function: 1
&main: 8
&function: 8
main(): 4
function*: 8
---------------字串----------------
str1[] = "12345\0678": 7
str1[] = "12345\0678": 8
str2[] = "12345\\0678": 10
str2[] = "12345\\0678": 11
char ArryNames[9][8]: 72
char ArryNames[9][8]: 3
char* names[9]: 72
------------修改對齊方式-------------
struct Pragma_2: 16
struct Pragma_1: 10
    -----------------------------    
****在32位系統上,各型別佔用位元組數****
****  Visual Studio 2010 win32   ****
    -----------------------------    
-------------基本型別----------------
char: 1
unsigned char: 1
short: 2
unsigned short: 2
int: 4
unsigned int: 4
float: 4
double: 8
long: 4
unsigned long: 4
long long: 8
---------列舉、結構、聯合------------
enum: 4
struct person8: 40
struct person4: 12
struct person2: 6
struct person1: 1
union IPV4: 4
--------指標、函式、函式指標---------
char*: 4
int*: 4
long long*: 4
double*: 4
&main: 4
&function: 4
main(): 4
function*: 4
---------------字串----------------
str1[] = "12345\0678": 7
str1[] = "12345\0678": 8
str2[] = "12345\\0678": 10
str2[] = "12345\\0678": 11
char ArryNames[9][8]: 72
char ArryNames[9][8]: 3
char* names[9]: 36
------------修改對齊方式-------------
struct Pragma_2: 16
struct Pragma_1: 10
請按任意鍵繼續. . .
    -----------------------------    
****在64位系統上,各型別佔用位元組數****
****   Visual Studio 2010 X64    ****
    -----------------------------   
-------------基本型別----------------
char: 1
unsigned char: 1
short: 2
unsigned short: 2
int: 4
unsigned int: 4
float: 4
double: 8
long: 4
unsigned long: 4
long long: 8
---------列舉、結構、聯合------------
enum: 4
struct person8: 40
struct person4: 12
struct person2: 6
struct person1: 1
union IPV4: 4
--------指標、函式、函式指標---------
char*: 8
int*: 8
long long*: 8
double*: 8
&main: 8
&function: 8
main(): 4
function*: 8
---------------字串----------------
str1[] = "12345\0678": 7
str1[] = "12345\0678": 8
str2[] = "12345\\0678": 10
str2[] = "12345\\0678": 11
char ArryNames[9][8]: 72
char ArryNames[9][8]: 3
char* names[9]: 72
------------修改對齊方式-------------
struct Pragma_2: 16
struct Pragma_1: 10
請按任意鍵繼續. . .
### 總結
- 對於GCC編譯器而言,32位與64位的差別主要體現在三個方面
   - 位元組32位預設以4位元組對齊,64位以8位元組對齊
   - 對於指標32位佔用4位元組,64位佔用8位元組
   - long型在32位上佔用4位元組,64位佔用8位元組
- 對於VS2010編譯器而言,32位與64位的區別
   - 32位和64位預設都以結構體的自身對齊值對齊,除非指定比自身對齊值小的對齊值
   - 對於指標32位佔用4位元組,64位佔用8位元組
   - long型在32位和64位都佔用4位元組
------
## C++語言
------
### C++程式碼32位註釋

​```C++
/*************************************************************************
    > Description: C++基本型別、類在32位GCC4.8.4 編譯器下佔用的記憶體大小
 ************************************************************************/

#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>

using namespace std;

enum color {
    BLACK = 0,
    YELLOW = 1,
    WHITE,
    BLUE
};  //4 Byte

/*
 * 位元組對齊原則:
 *   1.資料型別自身的對齊值:對於char型資料,為1;對於short型,為2,對於int,float型,為4;double型別,為8,單位位元組
 *   2.結構體或者類的自身對齊值:其成員中自身對齊值最大的那個值
 *   3.指定對齊值:#pragma pack (value)時的指定對齊值value。
 *   4.資料成員、結構體和類的有效對齊值:自身對齊值和指定對齊值中小的那個值
 * 注意:32位GCC預設指定對齊為4位元組,64位GCC預設指定對齊為8位元組
 *     VS2010不管是32位還是64位編譯器,其預設指定對齊值為結構體或者類的自身對齊值(成員中自身對齊值最大的值)
 */
struct person8 {
    char gender;    //佔用2位元組,自身1位元組
    short age;      //佔用2位元組
    char party;     //佔用4位元組,自身1位元組
    int height;     //佔用4位元組
    char name[5];   //佔用8位元組,自身5位元組
    double weight;    //佔用8位元組
    char addr;      //佔用4位元組,自身1位元組
};  //32 Byte   有效對齊值4

struct person4 {
    char gender;    //佔用2位元組,自身1位元組
    short age;      //佔用2位元組
    char party;     //佔用4位元組,自身1位元組
    int height;     //佔用4位元組
};  //12 Byte   有效對齊值4

struct person2 {
    char gender;    //佔用2位元組,自身1位元組
    short age;      //佔用2位元組
    char party;     //佔用2位元組,自身1位元組
};  //6 Byte   有效對齊值2

struct person1 {
    char gender;    //佔用1位元組,自身1位元組
};  //1 Byte   有效對齊值1

/*
 * #pragma pack(1/2/4/8)修改指定對齊位元組數
 * 注意:修改並不一定能奏效,因為還要看結構中成員最大那個對齊值
 *      成員最大對齊值超過指定對齊值,指定才能起作用
 */
#pragma pack(2)
struct Pragma_2
{
    int   a;    //4
    char  b;    //2
    double c;   //8
    char  d;    //2
};  //16 Byte   有效對齊值2

#pragma pack(1)
struct Pragma_1
{
    char  a;    //1
    double b;   //8
    char  c;    //1
};  //10 Byte   有效對齊值1
#pragma pack()

typedef struct IP {
    unsigned char szIP1;    //high
    unsigned char szIP2;
    unsigned char szIP3;
    unsigned char szIP4;
}IP_INT;

typedef union IP_addr {
    IP_INT ip_int;
    int ipv4;
    char type;
}IP_ADDR;   //4 Byte

static double function(int a, float b)
{
    return 0;
}

/*
 * 1.類的大小為類的非靜態成員資料的型別大小之和,也就是說靜態成員資料不作考慮;
 * 2.類的總大小也遵守類似class位元組對齊的;
 * 3.成員函式都是不會被計算的; 
 * 4.如果是子類,那麼父類中的成員也會被計算;
 * 5.虛擬函式由於要維護虛擬函式表,所以要佔據一個指標大小,也就是4位元組.
 * 總結:一個類中,虛擬函式、成員函式(包括靜態與非靜態)和靜態資料成員都不佔用類物件的儲存空間
 */
class Person {
private:
    unsigned short age; //佔用2位元組
    bool gender;        //佔用1位元組
    char name[16];      //佔用17位元組
public:
    /* 聯合,佔用16位元組 */
    union UBffer
    {
        char buffer[13];
        int number;
    }ubuf;

    typedef char*(*f)(void*);   //不佔用類物件記憶體
    enum{hdd,ssd,blueray}disk;  //佔用4位元組,按int儲存

    /* 成員函式,不佔用類物件的記憶體 */
    Person(const char* name, bool gender, unsigned short age) {
        strcpy(Person::name, name);
        Person::gender = gender;
        Person::age = age;
    }

    ~Person() {cou