问题摘自《深度探究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. js手机号批量滚动抽奖代码实现

    我们平时在看一些选秀节目或一些歌唱类比赛节目时经常会看到在现场的大屏幕上会有观众的手机号在滚动来选出谁是幸运观众或谁中了什么奖项,这些手机号都是现场观众或场外观众在给选手投票时产生的,当主持人一声开始 ...

  2. [ios2]iOS 使用subversion管理iOS源代码 【转】

    使用subversion管理iOS源代码 1.安装和配置subversion服务器 在windows 服务器上安装VisualSVN-Server,下载地址http://www.visualsvn.c ...

  3. java类构造器的理解

    子类不能继承父类的构造器(构造方法或者构造函数),但是父类的构造器带有参数的,则必须在子类的构造器中显式地通过super关键字调用父类的构造器并配以适当的当属列表. 如果父类有无参构造器,则在子类的构 ...

  4. for循环和while循环

    for循环和while循环 --道心 for循环 name1_list=['daoxin','wuxin','zhixin']for ele in name1_list: #找到"wuxin ...

  5. ASP.NET Zero--3.菜单配置

    配置一个如上图所示的菜单   1.打开文件MpaNavigationProvider.cs [..\MyCompanyName.AbpZeroTemplate.Web\Areas\Mpa\Startu ...

  6. 使用Netsil监控Kubernetes上的微服务

    ubernetes是容器编排和调度领域的王者,它击败了竞争对手Docker Swarm和Apache Mesos,开启了闪耀的未来,微服务可以自修复,可以自动扩展,可以跨zone,region甚至跨云 ...

  7. Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if expl

    检查你的用户名和密码是否正确 ,以及位置是否正确:

  8. 前端——HTML笔记Two

    web前端需要掌握:HTML.CSS.JavaScript语言.这三门技术用来实现: 1. HTML是网页内容的载体.内容就是网页制作者放在页面上想要让用户浏览的信息,可以包含文字.图片.视频等. 2 ...

  9. Kali

    http://zydhacker.blog.163.com/blog/static/211795073201447337920/

  10. MATLAB ' : ' 官方解释

    1.冒号的作用 产生矢量,阵列标注以及for-loop迭代子 2.描述 冒号是MATLAB中最有用的操作符之一.它使用下述规则来创建有规则的空间矢量: j:k is the same as [j,j+ ...