The operator of C++ : sizeof

    Recently I was reviewing C++ . And I was interested in TYPEOF , this operator . You can use it Like " sizeof( testedVariable ) " to see the size of testedVariable . You might think it is a function . But it is not . it is a operator , not a function . So don't mess it . But I wondered how it works . I mean sometimes the result comes I don't understand . ex: 

#include <iostream>
using namespace std;

struct myStruct {
    char a;
    int b;
};

int main() {
    
    cout<<sizeof(myStruct); // the result is 8(in 64 bit) , not 5 !
    
    cout<<endl;
    
    return 0;
}

    So I dug something about it . Turns out , it has rules to calculate . NOT just add them together . But I will start form the simple part . 

    First , the basic data types . We both know that int type takes 4 bytes in 64 bit CPU , and takes 2 bytes in 32 bit CPU . Let's talk about the differences between the 32 bit CPU and 64 bit CPU . For the data type , only two data types , int and pointer , are different . 

data typeint short longcharfloatdoublelong double pointer
32 bit22414884
64 bit 42414888
 

    So , the basic data types :

    int intType = 0;
    
    short shortType = 0;
    
    long longType = 0;
    
    char charType = 'c';
    
    float floatType = 0.1;
    
    double doubleType = 1.0;
    
    long long longlongType = 1;
    
    int *intPointer;
    
    char *stringPointer = "Hello World";
    
    char arrayStringPointer[] = "Hello World";
    
    cout<<"intType : "<<sizeof( intType )<<endl; // 4
    
    cout<<"shortType : "<<sizeof( shortType )<<endl; // 2
    
    cout<<"longType : "<<sizeof( longType )<<endl; // 8
    
    cout<<"charType : "<<sizeof( charType )<<endl; // 1
    
    cout<<"floatType : "<<sizeof( floatType )<<endl; // 4
    
    cout<<"doubleType : "<<sizeof( doubleType )<<endl; // 8
    
    cout<<"longlongType : "<<sizeof( longlongType )<<endl; // 8
    
    cout<<"intPointerType : "<<sizeof( intPointer )<<endl; // 8
    
    cout<<"stringPointerType : "<<sizeof( stringPointer )<<endl; // 8
    
    cout<<"stringType : "<<sizeof( "Hello World" )<<endl; // 12
    
    cout<<"another stringType : "<<sizeof( "Hello World ! " )<<endl; // 15
cout<<"arrayStringPointerType : "<<sizeof( arrayStringPointer )<<endl; // 12

     Here it is , I think most of them you would understand , except for the last three lines . The results of the last three lines , depend the values, AKA , the strings . So , now you see .  

    Next , the struct . First , let's back to the first example I wrote and think about it . Why ? So , it has one rule about " align in CPU " thing . It means that the sizeof will just calculate integral multiple sizes . It means that the result must be the integral multiple of 4 , well , in 64 bit . So it will be different when you change the order of the properties . Because it will add bytes till the offset of CPU is the integral multiple of the next property's type . For example , the first property is int type , the second property's type is char . In the beginning , the offset is 0 , and it will be 4 when comes the first property . and then the second comes , it will check the offset now is the integral multiple of the number of bytes this property takes or not . If it is not , it will add bytes to let the offset be the integral multiple of 4 . And go on by this rule . Hope you understand . Let's see the demo : 

struct emptyStruct {
};

struct firstStruct {
    char a;
};

struct secondStruct {
    char a;
    int b;
    char c[17];
    int d;
};

int main() {
    
    cout<<"emptyStruct : "<<sizeof( emptyStruct )<<endl; // 1
    
    cout<<"firstStruct : "<<sizeof( firstStruct )<<endl; // 1
    
    cout<<"secondStruct : "<<sizeof( secondStruct )<<endl; // 32
    
    cout<<endl;
    
    return 0;
}

    So you see , empty struct takes 1 . And this is not weird , because it is a empty pointer , for us to get it . 

    Then , class . It is almost the same as above . Let's see the code first : 

class emptyClass {
};

class staticClass {
public:
    static int a;
};

class functionClass {
public:
    int a();
};

class normalClass {
public:
    normalClass();
    ~normalClass();
    void d();
private:
    int a;
    char b;
    static char c;
};

class normalClassWithVirtualFunction {
public:
    normalClassWithVirtualFunction();
    ~normalClassWithVirtualFunction();
    void virtual d();
private:
    int a;
    char b;
    static char c;
};

class parentClass {
public:
    parentClass();
    ~parentClass();
    void d();
private:
    int a;
    char b;
    float c;
    static char e;
};

class subClass : public parentClass {
public:
    subClass();
    ~subClass();
    void f();
private:
    int a;
    char b;
    float c;
    static char e;
};


int main() {
    
    cout<<"emptyClass : "<<sizeof( emptyClass )<<endl; // 1
    
    cout<<"staticClass : "<<sizeof( staticClass )<<endl; // 1
    
    cout<<"functionClass : "<<sizeof( functionClass )<<endl; // 1
    
    cout<<"normalClass : "<<sizeof( normalClass )<<endl; // 8
    
    cout<<"normalClassWithVirtualFunction : "<<sizeof( normalClassWithVirtualFunction )<<endl; // 16
    
    cout<<"parentClass : "<<sizeof( parentClass )<<endl; // 12
    
    cout<<"subClass : "<<sizeof( subClass )<<endl; // 24
    
    return 0;
}
    As you see , the empty class , the class with static properties and the class with function , all take one byte in CPU . Because even if the classes have not their own properties , well not static , but we still need to ID them , means that we need to get them somehow , and this is how , we give them a pointer . And the normal classes , well , not so special , just like struct . We just count the size of the super class to the subclass . 

    Finally , the virtual inherit class . As we know , the subclass will create a virtual function class when it is virtual inherit form the super class . AKA , a pointer , means takes 8 bytes in 64 bit CPU . And it is not like struct ,  in this case , the CPU will give the class 8 bytes each time , in 64bit CPU which means the result is integral multiple of 8 . Let's see the code : 

class parentClassWithoutVirtualFunc {
public:
    parentClassWithoutVirtualFunc();
    ~parentClassWithoutVirtualFunc();
    void d();
private:
    int a;
};

class parentClassWithVirtualFunc {
public:
    parentClassWithVirtualFunc();
    ~parentClassWithVirtualFunc();
    void virtual d();
};

class subClass1 : public virtual parentClassWithoutVirtualFunc {
public:
    subClass1();
    ~subClass1();
private:
    int a;
    char b;
    float c;
};

class subClass2 : public virtual parentClassWithoutVirtualFunc {
public:
    subClass2();
    ~subClass2();
private:
    char a[15];
};

class subClass3 : public virtual parentClassWithoutVirtualFunc {
public:
    subClass3();
    ~subClass3();
private:
    char a[23];
};


int main() {
    
    cout<<"parentClassWithoutVirtualFunc : "<<sizeof( parentClassWithoutVirtualFunc )<<endl; // 4
    
    cout<<"parentClassWithVirtualFunc : "<<sizeof( parentClassWithVirtualFunc )<<endl; // 8
    
    cout<<"subClass1 : "<<sizeof( subClass1 )<<endl; // 24
    
    cout<<"subClass2 : "<<sizeof( subClass2 )<<endl; // 32
    
    cout<<"subClass3 : "<<sizeof( subClass3 )<<endl; // 40
    
    return 0;
}

    So , there it is . Hope it will help you . And for the record , it is true on 64 bit CPU . Well you can try in 32 bit CPU . 




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值