美文网首页程序员iOS 面试题寒哥管理的技术专题
05·iOS 面试题·Sizeof与Strlen的区别与联系

05·iOS 面试题·Sizeof与Strlen的区别与联系

作者: pengxuyuan | 来源:发表于2018-09-27 00:21 被阅读9次

    前言

    sizeof()strlen() 在平时开发中使用的频率相对没那么高,个人觉得简单了解它们的用法及区别就 OK 了;最近刚好遇到一个用 sizeof() 计算结构体占用内存空间的问题,我们顺便也扯一扯这个吧。

    这篇文章首先我们简单讲一下 sizeof()strlen() 的区别,然后了解下基本变量类型在 iOS 中占用多少内存空间,然后再扯一下如何计算结构体占用的内存空间大小,进而引申出字节对齐这个机制;最后总结在编写结构体的时需要注意的点。

    sizeof() 跟 strlen() 的区别

    简单来说: sizeof() 是运算符,在编译时期计算参数占用多少内存空间大小;strlen() 是一个函数,在运行时计算字符串的长度;

    所以我感觉就是两个东西,也不是很清楚这两个有什么联系,不知道为什么会有这样奇怪的题目,可能我还没 get 到点吧,有人知道还望请告知。

    基本数据类型在 iOS 中占用内存空间大小问题

    这里直接用表格列举出来吧:

    基本数据类型 32 位系统占用字节数 64位系统占用字节数
    char 1 1
    char * 4 8
    short int 2 2
    int 4 4
    unsigned int 4 4
    long 4 8
    long long 8 8
    unsigned long long 8 8
    float 4 4
    Double 8 8

    结构体占用内存空间大小问题

    为了更加清晰了解结构体占用内存空间的问题,我们先来分析下面代码示例:

    typedef struct
    {
        char  member1; //1字节
        short member2; //2字节
        int   member3; //4字节
    }Family;
    
    typedef struct
    {
        char  member1; //1字节
        int   member3; //4字节
        short member2; //2字节
    }Family2;
    
    NSLog(@"Family size is %zd",sizeof(Family));
    NSLog(@"Family2 size is %zd",sizeof(Family2));
    //Family size is 8
    //Family2 size is 12
    

    看到 Log 结果,我们可能有两个疑问:

    1. 为什么 size 结果不是 7
    2. 两个结构体成员变量是一样的,顺序不同为什么会导致 size 不一样

    这里其实涉及到了内存对齐,我们就简单说下需要内存对齐的原因以及内存对齐的规则,再详细的知识点可以看下文末的参考链接。

    首先变量存放在内存中是不能随意存的,需要有一定的规则,在特定的地址才能存放特定的变量,这就导致变量在内存空间上不是简单的排序排列,需要一定的规则,为了达到这个规则,我们就需要内存对齐。

    内存对齐的原因:

    1. 某些平台只能在特定的地址访问特定类型的数据
    2. 提高存取数据的速度

    结构体内存对齐规则,摘抄自 一张图理解内存对齐

    1. 结构体中的第一个成员的首地址也即是结构体变量的首地址。
    2. 结构体中的每一个成员的首地址相对于结构体的首地址的偏移量(offset)是该成员数据类型大小的整数倍。
    3. 结构体的总大小是对齐模数(对齐模数等于#pragma pack(n)所指定的n与结构体中最大数据类型的成员大小的最小值)的整数倍。

    通过上面规则我们可以很轻松的计算出上面代码结构体占用的大小:

    typedef struct
    {
        char  member1; //1字节
        short member2; //2字节
        int   member3; //4字节
    }Family;
    
    // 对于这个结构体:1+`1`+2+4 = 8字节 `1` 是补齐字节
    
    typedef struct
    {
        char  member1; //1字节
        int   member3; //4字节
        short member2; //2字节
    }Family2;
    
    // 对于这个结构体:1+`3`+4+2+`2` = 12字节,`3` 和 `2` 是补齐字节
    

    这里可能有点晦涩难懂,大家可以具体看看这篇博客:C语言 - 结构体所占字节数 ,我这里再摘抄的话,也没什么意思;

    反正对于计算结构体占用内存大小,大家需要注意有内存对齐这个东西就好了。

    编写结构体注意事项

    对于结构体占用内存空间这个,不是我们程序的性能瓶颈,但是学完这个面试题,我觉得掌握以下两个点挺好的:

    1. 写结构体时,尽量将成员变量按照占用内存空间从小到大排序
    2. 面对一些源码时,可以知道手动内存补齐这东西

    例如下面 RunLoop 源码, _padding[3] 这个成员变量没有实际的意义,只是用来内存补齐的。

    struct __CFRunLoopMode {
        CFRuntimeBase _base;
        pthread_mutex_t _lock;  /* must have the run loop locked before locking this */
        CFStringRef _name;
        Boolean _stopped;
        char _padding[3];
        CFMutableSetRef _sources0;
        CFMutableSetRef _sources1;
        CFMutableArrayRef _observers;
        CFMutableArrayRef _timers;
        //……
    };
    

    总结

    这篇文章只是简单的说了下 sizeof()strlen() 的区别,然后聊了下将最近遇到结构体计算内存空间大小的问题,认识到了还有内存对齐这个东西;

    感觉这篇有点水,主要还是说引申一些知识点,增加下知识的广度吧,对于我自己还是学到了一些的,关于更深度的东西,依旧,参考文献很优秀。

    参考文献

    iOS 笔试题 Sizeof与Strlen的区别与联系

    C语言 - 结构体所占字节数

    iOS32位和64位的坑

    一张图正确理解内存对齐

    iOS 内存字节对齐

    https://www.jianshu.com/p/a371e2613ec8

    iOS结构体的内存分配问题

    C 语言结构体内存布局问题

    C语言struct内存占用问题

    相关文章

      网友评论

        本文标题:05·iOS 面试题·Sizeof与Strlen的区别与联系

        本文链接:https://www.haomeiwen.com/subject/vrjsoftx.html