zoukankan      html  css  js  c++  java
  • 字节对齐,sizeof,strlen,_countof,offsetof,_msize

    一、sizeof

    sizeof()返回值最好用size_t保存,在x86和x64下,该类型有不同的表示,unsigned int(32位),unsigned __int64(64位)

    #include <iostream>
    #include <string>
    #include <vector>
    
    int main()
    {   
        int arrx[20];
        auto n = _countof(arrx);  //n = 20,返回值类型为unsigned int 宏_countf定义在stdlib.h,c++包含vector头文件也可以使用
        
        //sizeof返回值的类型是size_t,unsigned int(32位),unsigned __int64(64位)
        char ch1[] = "HelloWorld";
        char* ch2 = ch1;   //sizeof(ch2)
        int arr1[] = { 1,2,3,4,5,6,7 };
        int* arr2 = arr1;
        std::string str1 = "HelloC++";
        std::string str2;
    
        size_t s1 = sizeof(ch1);  //11,"HelloWorld"因为是内存占用的空间大小,所以包含最后的字符串结束符号,所以是10+1=11
        size_t s2 = sizeof(ch2);  //和编译器平台有关,sizeof(ch2)得到的是指针的大小,x64为8,x86为4
        size_t s3 = sizeof(str1); //sizeof(str)得到的是string对象的大小,是一个固定值,和str具体内容无关
        size_t s4 = sizeof(str2); //64位:40,32位:28
        size_t s5 = sizeof(arr1); //28   一个int占4个字节,7*4=28
        size_t s6 = sizeof(arr2); //指针的大小,和编译器平台有关,32位:4,64位:8
    
        size_t s01 = sizeof((*ch1));  //1
        size_t s02 = sizeof((*ch2));  //1
        size_t s03 = sizeof((*arr1)); //4
        size_t s04 = sizeof((*arr2)); //4 解引用得到的都是第一个元素类型的大小 char:1,int:4
    
        size_t s7 = str1.length();//8,字符串的长度,有几个字符就是几,不包含字符串结束符
        size_t s8 = strlen(ch1);  //10,strlen(str1)错误,strlen的参数为const char*,字符串的长度,有几个字符就是几
        size_t s9 = str1.size();  //8,同str.length(),size还可用于获取容器的大小
    
        std::vector<std::string> vec;
        vec.emplace_back("abcdef");
        vec.emplace_back("123");
        vec.emplace_back("qwert");
        size_t s10 = vec.size();   //3
        size_t s11 = sizeof(vec);  //和元素的个数无关,64位:32,32位:16,应该是存放了四个指针(不确定)
        size_t s12 = sizeof(std::vector<bool>); //bool比其他类型大1/2,即64:48,32:24,
        size_t s13 = sizeof(std::vector<int>);  //16,32
        size_t s14 = sizeof(std::vector<std::string>);  //16,32
        size_t s15 = sizeof(std::vector<char>); //16,32
    
        return 0;
    }
    

    二、字节对齐

    #include <iostream>
    
    int main()
    {
        struct s1  //16
        {
            int i;
            char c;
            double d;
        };
        struct s2   //16
        {
            double d;
            char c;
            int i;
        };
        struct s3  //16
        {
            char c;
            int i;
            double d;
        };
        struct s4  //24
        {//结构体中占用空间最大的类型为8(double),1+7 + 8 + 4 = 20 不是8的倍数,所以要填充4个字节,满足sizeof(double)=8的倍数
            char c;
            double d;
            int i;
        };
        std::cout << sizeof(s1) << sizeof(s2) << sizeof(s3) << sizeof(s4) << std::endl;
    #pragma pack(push) //保存对齐状态    push和pop是一对,不用push和pop包住,pack(n)将会对后面的所有sizeof生效
    #pragma pack(4)    //设定为4字节对齐
        struct t1
        {
            char m1;
            double m4;
            int  m3;
        };
        std::cout << sizeof(t1) << std::endl;  //16
    #pragma pack(pop)//恢复对齐状态
        struct t2
        {
            char m1;
            double m4;
            int  m3;
        };
        std::cout << sizeof(t2) << std::endl;  //24
    
        return 0;
    }
    

    三、字符串长度

    cstring头文件(C风格字符串)

    strlen(str)计算字符串长度(有几个字符就返回几,不包含末尾的'')

    string头文件(std::string)

    str.size()返回字符串的长度(包括结尾的空字符,即空格也算,string类型的字符串结尾没有'')

    CString头文件(MFC)

    str.GetLength()返回的是字符个数(不包括结尾的空字符)

    四、sizeof(常见类型)

    1.sizeof(std::string)

    转载:string在内存中的布局

    名称 X86(字节数) X64(字节数)
    Allocator 4 8
    原始字符串Data位置 15 + 1,最多包含15个字符加一个结束符'' 15 + 1,最多包含15个字符加一个结束符''
    字符长度Size 4 8
    当前容量Capacity 4 8
    总计 28 40

    以下我们只讨论 32位程序

    • 对于长度小于等于15个字符的字符串:

    数据会保存到Data的总计16个字节中,如果string 是临时变量,整个字符串的数据位于栈上

    • 对于数据大于15个字符的字符串:

    会在堆上分配一块额外的数据区域,并将所有数据填充到堆中,然后将堆指针赋值到 Data 的第一个指针位置 (Data前4个字节)

    2.sizeof(容器)

    容器 x64 x86
    deque 40 20
    vector 32 16

    3.sizeof(class)

    class X{};
    class Y : public virtual X {};
    class Z : public virtual X {};
    class A : public Y,public Z {};
    
    sizeof(X) //1
    sizeof(Y) //4
    sizeof(Z) //4
    sizeof(A) //8
    

    X为1是因为编译器的处理,在其中插入了1个char,为了让其对象能在内存中有自己独立的地址Y,Z是因为虚基类表的指针A 中含有Y和Z所以是8

    五、一些用来获取字节数或元素个数的方法

    _countof

    windows宏,用来计算一个静态分配的数组中的元素的个数,返回值的类型为 unsigned int ,必须是静态分配的数组,不能是指针

    	char s1[] = "12345";
    	int s2[] = { 1,2,3,4,5 };
    	int* s3 = new int[10]();
    
    	auto ret1 = _countof(s1);  //6,包含''
    	auto ret2 = _countof(s2);  //5
    	//auto ret3 = _countof(s3); //error
    

    offsetof

    offsetof 会生成一个类型为size_t的整型常量,它是一个结构成员相对于结构开头的字节偏移量。成员是由 member-designator 给定的,结构的名称是在type 中给定的。

    _msize

    获取指针指向内容的实际大小(不是指针的大小),只能获取到new或malloc出来的指针指向内容的大小。

    #include <iostream>
    
    void fun(int* p)
    {
    	std::cout << sizeof(p) << '
    ';  //8  (x64)
    	std::cout << _msize(p) << '
    ';  //40 = 4*10
    }
    
    int main()
    {
    	int* p = new int[10]();
    	int p1[] = { 1,2,3 };
    
    	fun(p);
    	//fun(p1);  //不是new或malloc出来的指针,程序会崩溃
    
    	return 0;
    }
    
  • 相关阅读:
    《Intel汇编第5版》 汇编逆转字符串
    《Intel汇编第5版》 汇编拷贝字符串
    《Intel汇编第5版》 数组求和
    《Intel汇编第5版》 Mov指令
    CABasicAnimation 几种停止的回调
    模拟器SDK路径
    《Intel汇编第5版》 Intel CPU小端序
    《Intel汇编第5版》 汇编减法程序
    Iphone CPU 架构类型
    越狱开发-创建真正的后台程序(Daemon Process)
  • 原文地址:https://www.cnblogs.com/mmmmmmmmm/p/14088273.html
Copyright © 2011-2022 走看看