问题摘自《深度探究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. 创建基本的2D场景(part1)

    通过一个简单的2D游戏案例来学习unity 2D游戏开发,本文分为以下3个部分. · 创建工作层 · 添加静态景物 · 制作2D动画 通过这个案例,我们可以学习到unity2D游戏制作的基本流程,Sp ...

  2. 办理西蒙弗雷泽大学(本科)学历认证『微信171922772』SFU学位证成绩单使馆认证Simon Fraser University

    办理西蒙弗雷泽大学(本科)学历认证『微信171922772』SFU学位证成绩单使馆认证Simon Fraser University Q.微信:171922772办理教育部国外学历学位认证海外大学毕业 ...

  3. ASP文件上传代码

    在网上看到的代码,稍微有点问题,改了一下就可以了.Chrome下是可以用的,别的浏览器还没有确认. <% Response.Buffer = True Server.ScriptTimeOut= ...

  4. cocos2d基本类介绍 director/scene/layer/sprite

    [核心类]     导演Director.场景Scene.布景层Layer.精灵Sprite的概念请移步:     导演控制场景,场景控制图层,图层控制精灵,精灵控制动作.     相互之间的关系框架 ...

  5. socket select()模型

    转载:http://www.cnblogs.com/xiangshancuizhu/archive/2012/10/05/2711882.html 由于socket recv()方法是阻塞式的,当有多 ...

  6. 带分页、过滤条件的DSL

    "query": { "bool": { "must_not": { "match_phrase": { "p ...

  7. js 设计模式-接口

    js模拟java接口检测函数:确保子类实现接口中的方法:(出自js设计模式) 上代码: <script type="text/javascript" > <%-- ...

  8. 自定义dialog自动弹出软键盘

    1.解决无法弹出输入法: 在show()方法调用之前,用dialog.setView(new EditText(context))添加一个空的EditText,由于是自定义的AlertDialog,有 ...

  9. Tarjan算法详解

    Tarjan算法详解 今天偶然发现了这个算法,看了好久,终于明白了一些表层的知识....在这里和大家分享一下... Tarjan算法是一个求解极大强联通子图的算法,相信这些东西大家都在网络上百度过了, ...

  10. zabbix 布署实践【2 agent安装】

    客户端的安装相对较为简单,主要是更新它的repo源   以CentOS7为例 rpm -ivh http://repo.zabbix.com/zabbix/3.0/rhel/7/x86_64/zabb ...