1. 程式人生 > >c++資料型別(整型/浮點型/字串/陣列/引用/結構體(記憶體對齊)/類(虛擬函式))定義、所佔位元組數、最大最小值

c++資料型別(整型/浮點型/字串/陣列/引用/結構體(記憶體對齊)/類(虛擬函式))定義、所佔位元組數、最大最小值

#include<iostream>
#include<string>
#include<limits>
using namespace std;

int main()
{
    cout << "type: \t\t" << "************size**************"<< endl;
    cout << "bool: \t\t" << "所佔位元組數:" << sizeof(bool);
    cout << "\t最大值:" << (numeric_limits<bool>::max)();
    cout << "\t\t最小值:" << (numeric_limits<bool>::min)() << endl;
    cout << "char: \t\t" << "所佔位元組數:" << sizeof(char);
    cout << "\t最大值:" << (numeric_limits<char>::max)();
    cout << "\t\t最小值:" << (numeric_limits<char>::min)() << endl;
    cout << "   " << endl;
    cout << "signed char: \t" << "所佔位元組數:" << sizeof(signed char);
    cout << "\t最大值:" << (numeric_limits<signed char>::max)();
    cout << "\t\t最小值:" << (numeric_limits<signed char>::min)() << endl;
    cout << "   " << endl;
    cout << "unsigned char: \t" << "所佔位元組數:" << sizeof(unsigned char);
    cout << "\t最大值:" << (numeric_limits<unsigned char>::max)();
    cout << "\t\t最小值:" << (numeric_limits<unsigned char>::min)() << endl;
    cout << "wchar_t: \t" << "所佔位元組數:" << sizeof(wchar_t);
    cout << "\t最大值:" << (numeric_limits<wchar_t>::max)();
    cout << "\t\t最小值:" << (numeric_limits<wchar_t>::min)() << endl;
    cout << "short: \t\t" << "所佔位元組數:" << sizeof(short);
    cout << "\t最大值:" << (numeric_limits<short>::max)();
    cout << "\t\t最小值:" << (numeric_limits<short>::min)() << endl;
    cout << "int: \t\t" << "所佔位元組數:" << sizeof(int);
    cout << "\t最大值:" << (numeric_limits<int>::max)();
    cout << "\t最小值:" << (numeric_limits<int>::min)() << endl;
    cout << "unsigned: \t" << "所佔位元組數:" << sizeof(unsigned);
    cout << "\t最大值:" << (numeric_limits<unsigned>::max)();
    cout << "\t最小值:" << (numeric_limits<unsigned>::min)() << endl;
    cout << "long: \t\t" << "所佔位元組數:" << sizeof(long);
    cout << "\t最大值:" << (numeric_limits<long>::max)();
    cout << "\t最小值:" << (numeric_limits<long>::min)() << endl;
    cout << "unsigned long: \t" << "所佔位元組數:" << sizeof(unsigned long);
    cout << "\t最大值:" << (numeric_limits<unsigned long>::max)();
    cout << "\t最小值:" << (numeric_limits<unsigned long>::min)() << endl;
    cout << "long long: \t" << "所佔位元組數:" << sizeof(long long);
    cout << "\t最大值:" << (numeric_limits<long long>::max)();
    cout << "\t最小值:" << (numeric_limits<long long>::min)() << endl;
    cout << "double: \t" << "所佔位元組數:" << sizeof(double);
    cout << "\t最大值:" << (numeric_limits<double>::max)();
    cout << "\t最小值:" << (numeric_limits<double>::min)() << endl;
    cout << "long double: \t" << "所佔位元組數:" << sizeof(long double);
    cout << "\t最大值:" << (numeric_limits<long double>::max)();
    cout << "\t最小值:" << (numeric_limits<long double>::min)() << endl;
    cout << "float: \tt" << "所佔位元組數:" << sizeof(float);
    cout << "\t最大值:" << (numeric_limits<float>::max)();
    cout << "\t最小值:" << (numeric_limits<float>::min)() << endl;
    cout << "size_t: \t" << "所佔位元組數:" << sizeof(size_t);
    cout << "\t最大值:" << (numeric_limits<size_t>::max)();
    cout << "\t最小值:" << (numeric_limits<size_t>::min)() << endl;
    cout << "ssize_t: \t" << "所佔位元組數:" << sizeof(ssize_t);
    cout << "\t最大值:" << (numeric_limits<ssize_t>::max)();
    cout << "\t最小值:" << (numeric_limits<ssize_t>::min)() << endl;
    cout << "string: \t" << "所佔位元組數:" << sizeof(string) << endl;
    cout << "string:hello,world\t" << "所佔位元組數:" << sizeof("hello,world") << endl;
    char a[20];
    cout << "char a[20] \t" << "所佔位元組數:" << sizeof(a) << endl;
    int a1;
    int &ra=a1;
    cout << "int &ra \t" << "所佔位元組數:" << sizeof(ra) << endl;
    cout << "type: \t\t" << "************size**************"<< endl;
    return 0;
}
實驗結果:
一個位元組做為定義為byte=8bit,無符號資料 1)定義說明: 整型定義:包含整數、布林、字元三種算數型別。 wchar定義:它是c/c++字元型別,只一種擴充套件的儲存方式。因為char只有8位,最多能表示256個字元,但是許多外文字符集所包含的數目超過256個,char型無法表示。 size_t定義:一個基本的無符號整數的C / C + +型別, 它是sizeof操作符返回的結果型別 。 查詢步驟1./usr/include/linux/types.h
步驟2./usr/include/asm/posix_types.h
步驟3.1.64位/usr/include/asm-x86_64/posix_types.h

步驟3.2.32位/usr/include/asm-i386/posix_types.h
size_t就是一個無符號的整型,32位下對應為unsigned int,64位下為unsigned long。 ssize_t定義:size_t 就是無符號型的ssize_t。 查詢步驟1.vim /usr/include/bits/types.h
步驟2.vim /usr/include/bits/typesizes.h
步驟3.vim /usr/include/bits/types.h
綜上ssize_t在32位下對應為int,64位下為long int。 2)常見的使用規則: C99標準:
The rank of long long int shall be greater than the rank of long int,which

shall be greater than the rank of int,which shall be greater than the rank of short
int,which shall be greater than the rank of signed char.
所以int,short int,long int,long long int的寬度都可能隨編譯器而異。 但有幾條鐵定的原則:
sizeof(short int)<=sizeof(int) sizeof(int)<=sizeof(long int) sizeof(int)<=sizeof(long long int) short int至少應為16位, long int至少應為32位。
用long型別進行計算所付出的執行時代價遠遠高於用int型別進行同樣計算的代價,所以要先了解程式的細節並且比較long型別與int型別的實際執行時效能代價。 對於浮點數而言:使用double型別基本上不會有錯,在float型別中隱式的精度損失是不能忽視的。事實上在有些機器上,double型別比float型別的計算要快得多。float型只能保證6位有效數字,而double型至少可以保證15位有效數字,long double型提供的精度通常沒有必要,而且還要承擔額外的執行代價。 3)位元組數運算:

關於帶符號與無符號型別:整型 stort、int  和  long 都預設為帶符號型。要獲得無符號型則必須制定該型別為unsigned,比如unsigned long。unsigned int型別可以簡寫為unsigned。

一位元組表示八位,即:1byte = 8 bit;

int: 4byte =  32 bit 有符號signed範圍:2^31-1 ~ -2^31即:2147483647 ~ -2147483648 無符號unsigned範圍:2^32-1 ~ 0即:4294967295 ~ 0

double: 8 byte = 64 bit 範圍:1.79769e+308 ~ 2.22507e-308

float: 4 byte = 32 bit 範圍: 3.40282e+038 ~ 1.17549e-038 資料型別的範圍也跟OS、編譯器、機器有關等有關,浮點數的計算參照IEEE754。 引用就是變數的別名,所佔位元組數與該變數所佔位元組數一致。 陣列所佔位元組數與定義的型別有關:n*該型別所佔位元組數。 二、結構體 一個空的結構體所佔的位元組數為1個位元組 1byte=8bit 結構體所佔位元組數有以下兩條規則: 綜的說來就是結構體成員的對齊是用成員本身的大小和#pragma pack(push,n)中的n中較小的數對齊,例如如果成員大小為2,而你指定的對齊方式是4,則該成員按2對齊;結構本身的對其是用結構中最大成員的大小和#pragma pack(push,n)中的n較小的數對齊,即最後的園整,例如如果結構中最大成員大小8,而你指定對齊是16,則結構本身按8對齊。 1)結構體內部成員的對齊是取min(sizeof(成員型別),#pragma pack(push,n))。 2)整個結構體對其是取min(max(所有成員型別的sizeof),#pragma pack(push,n))。 例1:
#include <iostream>
#pragma pack(8)//設定為8位元組對齊
int main()
{
    struct Student
    {
        char a;
        int b;
        double c;
    };
    std::cout << "struct Student \t" << "所佔位元組數:" << sizeof(Student) << std::endl;
}


結果: 分析: 這個結構體的大小是16。設定編譯器8位元組對齊。a的大小是1,它就按1位元組對齊(min(sizeof(char),8)),存諸在0偏移的地方;b大小為4,它就按4位元組對齊(min(sizeof(int),8)),存在偏移4——7的位置,c大小為8(min(sizeof(double),8)),按8位元組對其,存在8——15的位置。這樣3個成員共佔用了16個位元組。由於該結構最大成員c大小為8(max(sizeof(char), sizeof(int), sizeof(double)),取min(max(sizeof(char), sizeof(int), sizeof(double),8),所以結構按8位元組對齊,16按8取整還是16,因此sizeof(Student) = 16。 例2:
#include <iostream>
#pragma pack(8)//設定為8位元組對齊
int main()
{
    struct Student
    {
        char a;
        int b;
        double c;
        char d;
    };
    std::cout << "struct Student \t" << "所佔位元組數:" << sizeof(Student) << std::endl;
}


結果:
分析: 前三個成員的儲存跟例1是一樣的,第四個d按min(sizeof(char),8)對齊,也就是按照1位元組對其,所以存在偏移位置16的地方。所佔位元組數為17。然後整個結構體對齊取min(max(sizeof(char),sizeof(int),sizeof(double)),8),也就是按照8對其。17對8取整,為24。所以整個結構體的偏移量為24。 例3:將編譯器對其位元組設定為4,pragma pack(4) #include <iostream>
#pragma pack(4)//設定為4位元組對齊
int main()
{
    struct Student
    {
        char a;
        int b;
        double c;
        char d;
    };
    std::cout << "struct Student \t" << "所佔位元組數:" << sizeof(Student) << std::endl;
}
結果:
分析: 結構體內部成員所佔位元組數同例2,然後整個結構體對其取min(max(sizeof(char), sizeof(int), sizeof(double)), 4),那麼取4位元組對齊。17對4取整為20,所以整個結構體所佔位元組數為20。 例4:
#include <iostream>
#pragma pack(4)//設定為4位元組對齊
int main()
{
    struct Student
    {
        char a[11];
        short b;
    };
    std::cout << "struct Student \t" << "所佔位元組數:" << sizeof(Student) << std::endl;
}


結果:
分析:陣列a按照min(sizeof(char),4),也就是1位元組對其,存貯在0-10的位置。b按min(sizeof(short),4),也就是2位元組對其。儲存在12-13的位置。整個結構體按照min(max(sizeof(char), sizeof(short)), 4)也就是2位元組對齊,14對2取整結果還是14。 關於結構體其他的一些說明: 先看下面的例子A:
#include <iostream>
#pragma pack(4)//設定為4位元組對齊
int main()
{
    struct Student
    {
        char a;
        int b;
        short c;
        int d;
    };
    std::cout << "struct Student \t" << "所佔位元組數:" << sizeof(Student) << std::endl;
}


結構體Studen所佔的位元組數:
例子B:
#include <iostream>
#pragma pack(4)//設定為4位元組對齊
int main()
{
    struct Student
    {
        int a;
        int b;
        short c;
        char d;
    };
    std::cout << "struct Student \t" << "所佔位元組數:" << sizeof(Student) << std::endl;
}


結構體Studen所佔的位元組數:
雖然例A與B都是定義的同一個結構體,但是由於記憶體對其的問題,導致他們所佔的位元組數不同。 這是編譯器自動設定了對齊,以空間換取時間效能。 但是如果按照B的方式宣告,則不管編譯器是否設定了對齊選項,都能夠正確的訪問資料。 有三種不同的處理方法:
1)     採用B的方式宣告
2)     對於邏輯上相關的成員變數希望放在靠近的位置,就寫成A的方式。有一種做法是顯式的插入reserved成員:
          struct Student{
            char a;
            char reserved1[3];
            int b;
            short c;
            char reserved2[2];
            int d;
}a;

3)     隨便怎麼寫,一切交給編譯器自動對齊。
三、類: 一個空類所佔的位元組數為1位元組。 如果類中含有資料成員所佔位元組數規則同第二部分結構體的規則。 例1:普通類
#include<iostream>
#pragma pack(4)
class Base
{
    int a;
    int b;
public:
    void CommonFunction();
};
int main()
{
    Base *base = NULL;
    std::cout << "sizeof(Base)=[" << sizeof(Base)<<"]"<< std::endl;
    return 0;
}


結果:
可見成員函式並不佔用記憶體,只有成員變數佔用記憶體。 例2:繼承基類:
#include<iostream>
#pragma pack(4)
class Base
{
public:
    void CommonFunction();
private:
    int a;
    int b;
};

class Derive : public Base
{
public:
    void DerivedCommonFunction();
private:
    int c;
};

int main()
{
    Base *base = NULL;
    Derive *derive = NULL;
    std::cout << "sizeof(Derive)=[" << sizeof(Derive)<<"]"<< std::endl;
    return 0;
}


結果:
子類繼承了父類的成員變數。加上自己的一個成員變數,所佔的位元組數為12。 請先參閱C++ 虛擬函式表解析http://blog.csdn.net/haoel/article/details/1948051/ 例3:含有虛擬函式:
#include<iostream>
#pragma pack(4)
class Base
{
public:
    virtual void CommonFunction();
private:
    int a;
    int b;
};

int main()
{
    Base *base = NULL;
    std::cout << "sizeof(Base)=[" << sizeof(Base)<<"]"<< std::endl;
    return 0;
}


結果:
相對於例1來說,多了一個虛擬函式之後,所佔位元組數多了8個位元組。這是由於在記憶體中增加了虛表指標,它的大小取決與sizeof(void*)的大小。 在本機的中sizeof(void*)=8 例4:虛繼承:
#include<iostream>
#pragma pack(4)
class Base
{
public:
    virtual void CommonFunction();
private:
    int a;
    int b;
};

class Derive : public Base
{
public:
    virtual void DerivedCommonFunction();
private:
    int c;
};

int main()
{
    Base *base = NULL;
    Derive *derive = NULL;
    std::cout << "sizeof(Derive)=[" << sizeof(Derive)<<"]"<< std::endl;
    return 0;
}


結果:
相對與例2來說,多了8個位元組。虛表指標並繼承,虛表指標只有一個,子類並不會生成新的虛表指標。

例5:多重繼承(有虛擬函式覆蓋)

#include<iostream>
#pragma pack(4)

class Base
{
public:
    virtual void CommonFunction();
private:
    int a;
    int b;
};

class Base2
{
public:
    virtual void CommonFunction2();
};
class Derive : public Base, public Base2
{
public:
    virtual void DerivedCommonFunction();
private:
    int c;
};

int main()
{
    Base *base = NULL;
    Derive *derive = NULL;
    std::cout << "sizeof(Derive)=[" << sizeof(Derive)<<"]"<< std::endl;
    return 0;
}
結果:
兩個父類的虛指標都被繼承,子類並不生成新的虛指標。相對於例5來說,多了一個虛指標所佔的位元組數目。 綜上所述: 1.一個類本身無論含有多少虛擬函式,它都只有一個虛指標,所佔位元組數為sizeof(void*)。 2.繼承一個父類,子類本身不會生成自己的虛指標,直接繼承父類的虛指標,所佔位元組數為sizeof(void*)。 3.繼承n個類,則子類繼承所有父類的虛指標,含有n個虛指標,所佔位元組數為n*sizeof(void*)。