(转载)http://www.cnblogs.com/sunyubo/archive/2012/07/04/2708241.html 
在标准 C 或者 C++ 中由于不支持 0 长度的数组,所以 int array[0]; 这样的定义是非法的。不过有些编译器的扩展功能支持 0 长度的数组。

在 C 中,0 长度的数组的主要用途是用来作为结构体的最后一个成员,然后用它来访问此结构体对象之后的一段内存(通常是动态分配的内存)。由于其非标准性,在程序中尽量避免使用 0 长度的数组。作为替换,可以使用 C99 标准中的不完整数组来替换 0 长度的数组定义。如:

CODE:
struct X {
  /* Members */
  int array[];  /* Do not write int array[0]; since it is not standard. */
};

>> 但是我的如下代码是能顺利编译且不出警告和错误,而且能运行的啊
>> int array[0]
>> *array = 1;

程序中可能出现的错误有多种。一是语法错误,这类错误很容易在编译阶段检查出来。除此之外,还有一类错误在编译阶段不能或者很难检查出来,这类错误被称为“无定义”,其结果是不确定的。

上面的代码中因为有越界访问数组这一错误存在,所以它的行为(执行的结果)是无定义的。
应用比如:
CODE:
struct A {
  int a, b;
  char data[0];
  /* do not write fields below */
};

struct A *p;

int n = 100, i;
p = malloc(sizeof(struct A) + n);
for (i = 0; i < n; ++i)
p->data[i] = 1;

摘自:http://hi.baidu.com/juneshine/blog/item/5aed91458bf5063e86947309.html

在GNU的指南中,它是如此写道:

struct line {
int length;
char contents[0];
};

//...ommit code here

struct line *thisline = (struct line *) malloc (sizeof (struct line) + this_length);
thisline->length = this_length;

这个用法主要用于变长Buffer,struct line的大小为4,结构体中的contents[0]不占用任何空间,甚至是一个指针的空间都不占,contents在这儿只是表示一个常量指针,这个特性是用编译器来实现的,即在使用thisline->contents的时候,这个指针就是表示分配内存地址中的某块buffer,比如malloc (sizeof (struct line) + this_length)返回的是0x8f00a40,thisline->contents指向的位置就是(0x8f00a40 + sizeof(struct line)),而这儿sizeof(struct line)仅仅是一个int的四字节。

对于这个用法,我们定义的结构体指针可以指向任意长度的内存buffer,这个技巧在变长buffer中使用起来相当方便。可能有朋友说,为什么不把最后的contents直接定义为一个指针呢?这儿的差别是这样的,如果定义为一个指针,它需要占用4Bytes,并且在申请好内存后必须人为赋地址才可以。如果使用这个用法,这个常量指针不占用空间,并且无需赋值。

这段代码的主要含义是定义了一个结构体,并对其进行初始化,上面结构体的第二个成员变量contents[0]事实上是不占内存空间的,因此整个结构体的长度sizeof(struct line)为4。当采用malloc为其申请内存空间时,如上所示,申请了一段长度为结构体长度加可变长度的内存空间给结构体类型的指针,这时contents就指向申请的可变长度的内存空间。由于是一次申请的,所以这段可变长度的内存空间和前面的结构体长度的内存空间是连续的。对于这段可变长度的内存空间,可以采用数组的方式对其进行访问。对于整个结构体,当不再使用时,可以使用free函数一次性对其进行释放,而不必像指针那样分别释放。

——>如果将零长数组array换成指针*array来使用的话,指针必须重新分配一段内存之后才能使用,那么当想要用socket发送结构体指针的时候,并不会将指针array申请的内存发送过去,因为是不连续的,所有接受socket发送来的数据后,会发现该数据并不是自己想要的。


例子1:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>struct Student
{int age;float tall;int addr_len;char addr[];
};int main(int argc, char** argv)
{int len = 100;struct Student* ptr;ptr = malloc(sizeof(struct Student) + sizeof(char) * len);ptr->age = 24;ptr->tall = 176.5;ptr->addr_len = len;strncpy(ptr->addr, "ZhuHai", sizeof("ZhuHai"));
free(ptr);  // 一次性释放malloc()分配的内存return 0;
}

例子2:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>struct Student
{int age;float tall;char *addr;
};int main(int argc, char** argv)
{struct Student* ptr;  // 不仅仅要分配两次内存
    ptr = malloc(sizeof(struct Student));ptr->addr = malloc(sizeof(char) * 100);ptr->age = 24;ptr->tall = 176.5;strncpy(ptr->addr, "ZhuHai", sizeof("ZhuHai"));
  // 而且要释放两次内存,并且它们的顺序不能颠倒了,否则会造成内存泄露
    free(ptr->addr);free(ptr);return 0;
}

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct Student
{
    int age;
    float tall;
    int add_len;
    char addr[0];  // 并不占内存
};

int main(int argc, char** argv)
{
    printf("The size: %d\n", sizeof(struct Student));

return 0;
}

程序输出:

12

可以看到长度为0那个数组,在实现上确实不占内存的。

转载于:https://www.cnblogs.com/Robotke1/archive/2013/05/12/3074065.html

(转载)C语言的零长数组相关推荐

  1. C语言0长度数组(可变数组/柔性数组)详解

    CSDN GitHub C语言0长度数组(可变数组/柔性数组)详解 AderXCoding/language/c/zero_length_array 本作品采用知识共享署名-非商业性使用-相同方式共享 ...

  2. C语言基础:数组作为函数参数传递演示源码

    将做工程过程中常用的内容片段记录起来,如下内容内容是关于C语言基础:数组作为函数参数传递演示的内容,应该能对小伙伴也有好处. #include <stdio.h>void show_arr ...

  3. C语言中动态数组的作用,C语言实现动态数组

    前言 在纯C语言编程中,数组的创建必须是固定的大小,因为C语言本身没有提供动态数组这种数据结构,这是一个让习惯了使用高级语言编程的人转做C开发面临的一个很头疼的问题,本篇文章就将介绍如何使用纯C语言编 ...

  4. GNU C 中的零长数组

    文章目录 什么是零长数组(Arrays of Length Zero) 零长数组的使用 零长数组和指针的区别 定义什么类型的零长数组 什么是零长数组(Arrays of Length Zero) 如果 ...

  5. C语言 指针和数组区别 - C语言零基础入门教程

    目录 一.前言 二.指针和数组区别 1.通过 sizeof 获取大小 a.计算数组大小 b.计算指针大小 2.指针和数组赋值方式不同 a.指针赋值 b.数组赋值 3.指针是指针变量,数组是指针常量 三 ...

  6. C语言 二维数组遍历 - C语言零基础入门教程

    目录 一.计算一维数组长度 二.计算二维数组长度 1.二维数组行数 2.二维数组列数 3.二维数组的元素个数 = 二维数组行数 * 二维数组列数 三.猜你喜欢 零基础 C/C++ 学习路线推荐 : C ...

  7. C语言 二维数组行数和列数计算 - C语言零基础入门教程

    目录 一.计算一维数组长度 二.计算二维数组长度 1.二维数组行数 2.二维数组列数 3.二维数组的元素个数 = 二维数组行数 * 二维数组列数 三.猜你喜欢 零基础 C/C++ 学习路线推荐 : C ...

  8. C语言 二维数组定义和使用 - C语言零基础入门教程

    目录 一.二维数组简介 二.定义二维数组并初始化 1.定义二维数组 2.初始化二维数组 三.访问二维数组 四.修改二维数组 五.猜你喜欢 零基础 C/C++ 学习路线推荐 : C/C++ 学习目录 & ...

  9. 计算payload长度c语言,C语言0长度数组(可变数组/柔性数组)详解

    1 零长度数组概念 众所周知, GNU/GCC 在标准的 C/C++ 基础上做了有实用性的扩展, 零长度数组(Arrays of Length Zero) 就是其中一个知名的扩展. 多数情况下, 其应 ...

最新文章

  1. set,存放不重复数据的集合类型
  2. VSS不需要验证自动登录的问题
  3. 怎么查看linux日志里请求量最高的url访问最多的_实用的Linux高级命令,开发运维都要懂!...
  4. LeetCode 504. Base 7 (C++)
  5. Shell脚本中计算字符串长度的5种方法
  6. 关于DButil的使用几点思考
  7. 用python实现简版区块链-交易(2)
  8. Python局域网内搭建文件共享服务器 上传文件
  9. [irving] C# Windows Beep 调用声音文件
  10. 通知短信、验证码短信、营销短信有什么不同
  11. UE4--材质地形篇——地形材质的运用(混合材质)
  12. Hacker_kid靶机打靶过程及思路
  13. 创新研发高通量芯片技术,JASMINER实现区块链芯片大突破
  14. JavaScript画漂亮的心形图案
  15. python写软件实例-如何编写Python软件开发文档(7个技巧)
  16. 杀毒软件 vs 射雕
  17. 【SystemVerilog基础】SystemVerilog语法之逻辑等(==)、全等(===)和匹配等(==?)
  18. 微信秒剪是什么意思 微信秒剪怎么剪辑视频发微信朋友圈
  19. 机器学习决策树算法cart剪枝
  20. usb-gadget

热门文章

  1. 先庆祝一下,冠军的心博客园诞生了!!
  2. 修复Long类型太长转为JSON格式的时候出错的问题
  3. [转] 如何在 CentOS7 中使用阿里云的yum源
  4. Error: Cannot find module 'babel-runtime/regenerator'
  5. HashMap中的hash函数
  6. 【AHOI2005】病毒检测
  7. 玩转HTML5移动页面(转自http://tqtan.com/)
  8. 电厂MIS,SIS简介
  9. Sharepoint学习笔记—ECMAScript对象模型系列-- 9、组与用户操作(二)
  10. javaweb开发中的那些坑