问题摘自《深度探究c++对象模型》:

struct mumble {
  /* stuff */
  char pc[ 1 ];
};【sizeof(mumble)是一个字节 。pc则代表的是指向这结构体中的这个字节的地址】

// grab a string from file or standard input【也就是下文的string,下文的string不是类型,是实际字符串】

// allocate memory both for struct & string
struct mumble *pmumb1 = ( struct mumble* ) malloc(sizeof(struct mumble)+strlen(string));  【这里不需要再加1了,尽管strlen是不包括\0的,因为pc中已经有一个字节了】              

strcpy( pmumb1->pc, string );【应该用变量名而不是结构体的名字,而且pc是指针了,不能再取地址了。】

下面答案摘自

把单一元素的数组放在一个struct的尾端  这个技巧可以用来在结构体中增加一个大小可以动态变化的字段,比如说一个buffer。pc其实就是一个指针,你可以申请一段内存,让pc指向它。

【那为什么一定要末尾呢,中间一个char pc[1]不行么?不行,如果是中间的话,就会把在他后面的数据给覆盖掉了。】

利用了下面的几个知识:
  1 c/c++当中指针的灵活性,指针相互之间是可以做转换的,没有类型条件限制内存地址可以按照不同类型的数据来解释
  2 struct 对象在内存当中的布局

malloc只负责分配一块指定大小的内存,并不做其他的事情,然后把内存的首地址返回
malloc关键词前面的(struct mumble *)强制类型转换,把这块内存转换为mumble类型数据了
实际上分配的内存要比一个mumble结构要大

memcpy这个函数是做内存当中数据的copy,它同样不检测数据的类型,即便是copy的数据超越了内存大小。
这个例子利用的也是这一点,把string当中的大量数据,copy到了mumble的pc变量所在的地址当中
因为malloc给这个地址分配了足够多的空间,copy超过1个char的数据到这里也不会产生实际的内存越界
后面对mumble.pc[n]  n>0 的访问,也是在malloc分配的空间当中,不会有异常

补充:

memcpy:内存复制  void *memcpy(void *dest, const void *src, size_t count);memcpy并不会遇到\0就结束,而是复制你在第三个参数中指定的字节数。
strcpy: 字符串复制    char * strcpy ( char * destination, const char * source );其复制遇到\0后就结束了

为什么 把单一元素的数组放在一个struct的尾端问题的更多相关文章

  1. 关于理解《C++ 对象模型》中:把单一元素的数组放在末尾,struct可以拥有可变大小的数组

    这一章在第19页,写的好深奥,我竟然没看明白在说什么--之后再看了几遍,终于明白了. 原文: C程序员的巧计有时候却成为c++程序员的陷阱.例如把单一元素的数组放在一个struct的末尾,于是每个st ...

  2. Leetcode 540.有序数组中的单一元素

    有序数组中的单一元素 给定一个只包含整数的有序数组,每个元素都会出现两次,唯有一个数只会出现一次,找出这个数. 示例 1: 输入: [1,1,2,3,3,4,4,8,8] 输出: 2 示例 2: 输入 ...

  3. Java实现 LeetCode 540 有序数组中的单一元素(位运算入门)

    540. 有序数组中的单一元素 给定一个只包含整数的有序数组,每个元素都会出现两次,唯有一个数只会出现一次,找出这个数. 示例 1: 输入: [1,1,2,3,3,4,4,8,8] 输出: 2 示例 ...

  4. 每天php函数 - 数组最后一个元素取出

    复制代码代码如下: $array=array(1,2,3,4,5);    echo $array[count($array)-1];//计算数组长度,然后获取数组最后一个元素,如果数组中最后一个元素 ...

  5. php删除数组中相同的元素,只保留一个相同元素

    <?php// 删除数组中相同元素,只保留一个相同元素function formatArray($array){sort($array);$tem = ”;$temarray = array() ...

  6. JavaScript利用数组原型,添加方法实现遍历多维数组每一个元素

    原型就是提供给我们为了让我们扩展更多功能的. 今天学习了用js模拟底层代码,实现数组多维的遍历.思想是在数组原型上添加一个方法. // js中的数组forEach方法,传入回掉函数 能够帮助我们遍历数 ...

  7. jQuery根据元素值或元素下标来删除一个数组元素及数组对象方法列表

    在前提不知道b在这个数组的下标,删除b这个元素  var arrList = ['a','b','c','d'];         arrList.splice(jQuery.inArray('b', ...

  8. js 获取数组最后一个元素

    当然有很多中做法 我这边就随便写几个最常用 最简单的方法把 # shift 删除数组第一个元素,并返回该元素,跟pop差不多 var a = ["aa","bb" ...

  9. 【C语言】求旋转数组的最小数字,输入一个递增排序的数组的一个旋转,输出其最小元素

    //求旋转数组的最小数字,输入一个递增排序的数组的一个旋转,输出其最小元素 #include <stdio.h> #include <string.h> int find_mi ...

随机推荐

  1. git shell 常用命令

    git branch 查看本地所有分支 git status 查看当前状态 git commit 提交 git branch -a 查看所有的分支 git branch -r 查看远程所有分支 git ...

  2. Java DB loadBalance 设计

    Java DB loadBalance 设计 */--> pre.src {background-color: #292b2e; color: #b2b2b2;} pre.src {backgr ...

  3. Linux软件安装管理 - CentOS (三)

    1. 软件包管理简介 2. rpm命令管理(Redhat Package Manager) 3. yum在线安装 4. 源码包管理 4.1 源码包和RPM包的区别 4.1.1 区别 安装前:概念上的区 ...

  4. 基于python第三方requests 模块的HTTP请求类

    使用requests模块构造的下载器,首先安装第三方库requests pip install requests 1 class StrongDownload(object): def __init_ ...

  5. VS2015 使用

    1,使用vs2015时,首先需要安装DAEMON Tools Lite虚拟光驱:

  6. MAC OS U 盘制作与安装方法

    伴随着 iMac 5K Retina 和新的 Mac mini 等硬件的发布,苹果终于都推出了 OS X Yosemite 系统正式版了!相信很多人都已经用上.不过对于一些不想升级,而是打算「全新安装 ...

  7. 解决Keras在IDE集成环境中找不到nvcc

    在我们正确配置了Keras使用GPU,并在Terminal中运行一切顺利的的时候,转到Pycharm或者Eclipse中运行有可能会出现"nvcc not found on the $PAT ...

  8. jsp页面根据当前时间和定义时间差计算动态倒计时

    jsp页面根据当前时间和定义时间差计算动态倒计时http://www.jb51.net/article/74140.htm    var maxtime =1000*60; //半个小时,按秒计算,自 ...

  9. Linux连接xshell找不到IP信息

    虚拟机环境下的Linux连接xshell的网络连接找不到eth0(IP)信息的解决方法   1  输入ifconfig,如果有eth0信息,直接填写eth0上面的IP信息   2 输入ifconfig ...

  10. RubyMine 2016.1 下载 附注册激活码 破解版方法

    注册破解方法: 在要求输入注册的界面选择激活码,然后粘贴以下注册码: 43B4A73YYJ-eyJsaWNlbnNlSWQiOiI0M0I0QTczWVlKIiwibGljZW5zZWVOYW1lIj ...