关于bennyhuo不是算命的老师视频的一些感悟。

首先看看这样一段结构体,在这段结构体中定义了一个没有制定长度的数组

typedef struct person {int age;char const* name;char intro[];
} Person;

平时我们在设置数组的时候,都会设置好数组的具体大小,比如uint8_t data[32],或者是使用指针uint8_t* data来表示一个不定长数组。还有,在传参的过程中,我们有时候需要传递一个数组,写成uint8_t* data或者是uint8_t data[]作用是相同的。

那么思考:在这个结构体里面,char* introchar intro[]是否相同呢?

初步分析

typedef struct person {int age;          // 4个字节的整型char const* name; // 对于64位程序来说,指本身也是一个变量,占8个字节char intro[];
} Person;

那么char intro[]呢?

我们都知道,数组的名字一般来说可以看作是一个地址,比如:

int a[10] = { 0 };
printf("%x", a);  // 10ffc3c

所以我们可以粗略的得出一个结果:

  • char* intro表示的是一个指针,它占8个字节,可以指向其他的任意地址
  • char intro[]表示的是一个地址,指向的是结构体内的地址

调试

现在我们来尝试着写一下创建对象的方法:

Person* newPerson(char const* name, int age, char const* intro) {size_t intro_len = (intro ? strlen(intro) : 0) + 1;           // 字符串都是以'/0'结尾Person* p = (Person*)malloc(sizeof(Person) + intro_len);p->age = age;p->name = name;if (intro) {strcpy(p->intro, intro);}else {p->intro[0] = 0;}return p;
}

然后在malloc动态开辟空间的时候打个断点看看:

注意一个十六进制数等于四个二进制数,一个字节有八位

比如0xcd可以表示为二进制11001101,这恰好为一个字节的长度

现在我们去0x000001463EE4EFF0看看那里有什么,目前看上去还是一团乱码:

往下走一步,将p->age = age;执行完毕看看:

再往下走一步,执行p->name = name;后再看看:

(关于字节的补齐可以参考字节对齐这个概念,我放在总结中介绍)

因此,我们使用sizeof(Person)方法,将会运算得出16。

现在,再往下走一步,执行p->intro的拷贝操作后再看看:

不难发现,p->intro部分紧紧的贴合在了p对象内存地址的后面。

总结

在结构体当中:

  • 长度为0的数组并不占有内存空间
  • 指针方式需要占用内存空间

在我们这个Person结构体当中:

  • 如果采用的是char intro[];,在分配内存时一次性将所需的内存全部分配给它,释放也是一次释放。数组和结构体的内存是连续的。
  • 而如果采用的是 char* intro;,首先,需为结构体分配一块内存空间;其次再为结构体中的成员变量指针分配内存空间。这样两次分配的内存是不连续的,需要分别对其进行管理。

另外,关于字节对齐:

它主要是针对结构体而言的,通常编译器会自动对其成员变量进行对齐,以提高数据存取的效率;理论上计算机对于任何变量的访问都可以从任意位置开始,然而实际上系统会对这些变量的存放地址有限制,通常将变量首地址设为某个数N的倍数,这就是内存对齐。

这里介绍默认对齐,默认对齐方式内存分配满足以下三个条件:

  • 结构体第一个成员的地址和结构体的首地址相同
  • 结构体每个成员地址相对于结构体首地址的偏移量是该成员大小的整数倍,如果不是则编译器会在成员之间添加填充字节
  • 结构体总的大小要是其成员中最大size的整数倍,如果不是编译器会在其末尾添加填充字节。

[ C语言 ] 结构体成员定义相关推荐

  1. linux c 结构体参数,C语言结构体类型定义

    C语言结构体类型定义 结构体的定义形式如下: struct 结构体名 { 结构体成员 }: 结构体变量的定义方式有三种: 1.先定义结构体,再定义变量: eg. struct student{ cha ...

  2. C语言结构体中定义函数指针详解

    C语言结构体中定义函数指针详解 结构体指针函数应用场景之一--驱动程序编写 结构体的一些基本用法 形式1:先定义结构体类型,再定义变量 形式2:在定义类型的同时定义变量 形式3:直接定义变量,用无名结 ...

  3. C语言结构体的定义与使用

    C语言结构体的定义与使用 1.结构体:存放不同数据的集合 (1)结构体内可以放入结构体typedef unsinged short ushortstruct Date{ushort year;usho ...

  4. C语言结构体成员有函数的定义与使用

    ```c#include <stdio.h> typedef int (*FunHandle)(int, int); //定义 指向函数的指针 struct Example {int a; ...

  5. C 语言结构体成员赋值的深拷贝和浅拷贝

    作者 | 李肖遥       责编 | 欧阳姝黎 最近在做通信协议的解析处理.传递分析等问题,总是遇到通信帧中的结构体拷贝等问题,遇到了一些坑,也是比较基础但是易错的C语言知识,一起来探究一下结构体的 ...

  6. C语言结构体的定义与使用、结构体数组、指向结构体的指针(有代码详解)

    1.结构体的定义与使用 结构体是一种构造数据类型 把不同类型的数据组合成一个整体 结构体的定义形式: struct 结构体名{结构体所包含的变量或数组 }; 结构体是一种集合,它里面包含了多个变量或数 ...

  7. c语言结构体成员变量默认值,C语言结构体要点笔记

    近日,做一个东西却发现自己在C语言,特别是结构体这个知识点上还缺乏认识.所以在学习了网友的分享后,下面在下文记录一些重要的要点吧. 一.struct是一种复合数据类型(这一点很重要,结构体只是一个类型 ...

  8. c语言结构体的定义与说明

    结构体类型的说明 在程序设计中,有时需要将不同类型的数据组合成一个有机的整体,以便于引用,在一个组合项中包含若干个类型不同(也可以相同)的数据项.c语言允许用户自己指定这样一种数据结构,称为" ...

  9. C语言 结构体的定义和用法

    1.结构体的定义: //定义一个结构体类型 struct Book{//书名,价格 char name[20];int price; }; 2.使用: //利用结构体类型-创建一个该类型的结构体变量 ...

最新文章

  1. ubuntu9.10硬盘安装记录二
  2. Hadoop的学习前奏(二)——Hadoop集群的配置
  3. Ubuntu 17.04 Chrome 安装
  4. 自己整理的排序算法之(1) 选择排序
  5. Android单元测试框架Robolectric3.0介绍(二)
  6. 算法笔记_231:网格中移动字母(Java)
  7. oe_runmake failed
  8. python判断点在矩形内_定义一个矩形和点的位置,判断点是否在矩形里面
  9. 2. PHP 自动转义函数
  10. 楼板计算塑形弹性_阶梯教室板模板支架工程方案计算书(仅供参考)
  11. lammps基础教程:Ovito标记原子内部运动方法介绍
  12. android重复点击屏幕,手机不ROOT.推荐一款android能用的屏幕连点器,类似按键精灵!...
  13. 新浪微博的Tab滑动效果
  14. Eclipse中出现无法找到Maven包Active Maven Profiles (comma separated)
  15. B. Remove Prefix
  16. 2020年国内优秀原创IT技术书都在这了
  17. vue将数据导出到excel
  18. 短信验证码常见漏洞总结
  19. CleanMyMac x2021中文版mac清理软件激活码下载
  20. 【干货书】图神经网络导论,清华大学刘知远老师著作

热门文章

  1. ABeam( 德硕 ) 携手北京优锘科技共同探讨”数字孪生可视化运营”方案
  2. 【分享】解读时间同步(NTP网络授时服务器)的重要性
  3. Safeboxie电脑版多开助手多开操作方法:
  4. vnc view使用教程
  5. PADS如何将导入的板框2D线转换成板框
  6. 微信公众号菜单点击发送天气预报
  7. GPS时钟系统在综自变电站中的应用
  8. 操作系统之 吸烟者问题
  9. LA2402 Fishnet 四边形面积
  10. stm32+hx711+蓝牙hc05 称重系统(蓝牙电子秤)