C99 flexible array number 伸缩型数组成员

这种特性用来射你那个结构体中最后一个成员是特殊成员,它是不存在的
它包含如下规则:
1、必须是最后一个数组成员
2、结构体中至少有一个其他成员
3、使用[]进行定义

/*************************************************************************
  > File Name: dongtai.c
  > Author: gaopeng
  > Mail: gaopp_200217@163.com
  > Created Time: Wed 25 May 2016 03:46:20 AM CST
 ************************************************************************/

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

#define LEN(a)  strlen(argv[a]) + sizeof(NFDATA) + 1

typedef struct nofixed
{
        int leng_t;
        char gs[];
} NFDATA;

int readpa(const int *ar,const int hmud)
{
        if(*ar == hmud)
        {
                return 1;
        }
        else
        {
                return 0;
        }

}

 

int main (int argc,char *argv[])
{
        FILE *fd;
        NFDATA *d1;
        NFDATA *d2;
        NFDATA *d3;

        if( readpa(&argc,5 ) != 1  )
        {
                printf("5 argc must\n");
                exit(1);
        }

        d1 = (NFDATA *)malloc(LEN(1));
        d1->leng_t = strlen(argv[1]);
        d1->gs[d1->leng_t] = '\0';
        memcpy(d1->gs , argv[1] , d1->leng_t);

        d2 = (NFDATA *)malloc( LEN(2));
        d2->leng_t = strlen(argv[2]);
        d2->gs[d2->leng_t] = '\0';
        memcpy(d2->gs , argv[2] , d1->leng_t);

        d3 = (NFDATA *)malloc( LEN(3));
        d3->leng_t = strlen(argv[3]);
        d3->gs[d3->leng_t] = '\0';
        memcpy(d3->gs , argv[3] , d3->leng_t);

        printf("argv1 %ld,%ld,%p,%p,%s,%d\n", sizeof(*d1),strlen(d1->gs),d1, d1->gs,d1->gs,d1->leng_t);
        printf("argv2 %ld,%ld,%p,%p,%s,%d\n", sizeof(*d2),strlen(d2->gs),d2, d2->gs,d2->gs,d2->leng_t);
        printf("argv3 %ld,%ld,%p,%p,%s,%d\n", sizeof(*d3),strlen(d3->gs),d3, d3->gs,d3->gs,d3->leng_t);
   
        if((fd = fopen(argv[4],"w")) == NULL)
        {
                printf("open file error!\n");
                exit(11);
        }

        fwrite(d1,1,LEN(1),fd);
        printf("file pointer: %ld\n",ftell(fd));
        fwrite(d2,1,LEN(2),fd);
        printf("file pointer: %ld\n",ftell(fd));
        fwrite(d3,1,LEN(3),fd);
        printf("file pointer: %ld\n",ftell(fd));

        free(d1);
        free(d2);
        free(d3);

        fclose(fd);

}

运行程序
./a.out  gao1 gao2 gao3 save3.dmp
这段代码就使用了这种特性将命令行参数这个不定的字符素组保存到了文件中,而且文件中没有浪费的空间
当然这样的做法也要内存中没有浪费的空间。不过兼容性可能有一些问题。
使用
 hexdump -Cv save3.dmp
查看二进制文件
00000000  04 00 00 00 67 61 6f 31  00 04 00 00 00 67 61 6f  |....gao1.....gao|
00000010  32 00 04 00 00 00 67 61  6f 33 00                        |2.....gao3.|
0000001b

如果要分析 实际上 ,主要取决于这里

#define LEN(a)  strlen(argv[a]) + sizeof(NFDATA) + 1

typedef struct nofixed
{
        int leng_t;
        char gs[];  //flexible array number
} NFDATA;

 d1 = (NFDATA *)malloc(LEN(1));
 d1->leng_t = strlen(argv[1]);
 d1->gs[d1->leng_t] = '\0'; 
 memcpy(d1->gs , argv[1] , d1->leng_t);

本来整个struct只需要4BYTES的空间,但是我们分配空间的时候加上了strlen(argv[a])+1
意思就是扩张一个参数长度+1出来,这里的+1就是保存'\0'结束符而已。
最后拷贝argv[1]的字符到d1->gs中

认为这种方式最好的地方在于内存中分配的空间的连续的 free起来方便,写文件也方便

如果
typedef struct nofixed
{
        int leng_t;
        char *gs; //a char pointer  
} NFDATA;
这种方式就不连续的,比较麻烦。

时间: 2024-09-23 02:23:56

C99 flexible array number 伸缩型数组成员的相关文章

数组与指针的艺术 第八章 柔性数组成员

  数组与指针的艺术 第八章 柔性数组成员 收藏 注意:本系列文章转自 csdn博客 http://blog.csdn.net/supermegaboy/archive/2009/11/23/4855027.aspx 感谢飞天御女猪大牛! 在讲述柔性数组成员之前,首先要介绍一下不完整类型(incomplete type).不完整类型是这样一种类型,它缺乏足够的信息例如长度去描述一个完整的对象. 6.2.5 Types incomplete types (types that describe o

结构体中的柔性数组成员(数组长度为0成员)!

其实很早在看LINUX下就看到这个东西,后来在MFC内存池里同样也看到了类似的东西,还依照MFC写过一个类似的小内存池,(MFC用的是return this + 1)后来在李先静的<系统程序员成长计划>里看到了类似的定义,于是心里想着总结一下,结果发现网上已经有牛人总结的很好了,于是乎就转了过来,谢谢你们的分享,这是我前进的动力!同时,需要引起注意的:ISO/IEC 9899-1999里面,这么写是非法的,这个仅仅是GNU C的扩展,gcc可以允许这一语法现象的存在.但最新的C/C++不知道是

[LeetCode] Circular Array Loop 环形数组循环

You are given an array of positive and negative integers. If a number n at an index is positive, then move forward n steps. Conversely, if it's negative (-n), move backward n steps. Assume the first element of the array is forward next to the last el

wcf-WCF中数据契约类包含数组成员时客户端报错,怎么解决

问题描述 WCF中数据契约类包含数组成员时客户端报错,怎么解决 WCF中数据契约类包含数组成员时客户端报错,怎么办呢?这个声明为数据契约的类是当成返回值传给客户端的,当数组成员赋值为null的时候客户端能正确接收到数据,但是当给这个数组成员赋予一个数组时客户端就不能读取这个返回的数据了.有高手有类似经验吗?望不啬赐教啊,很急 解决方案 你的数组元素的类型是什么,你的详细报错信息是什么 参考https://social.microsoft.com/Forums/nl-NL/da8c4e56-0a5

JavaScript中的Array 对象(数组对象)_javascript技巧

 1.创建Array对象方法: --->var arr = [1,2,3];//简单的定义方法 此时可以知道 arr[0] == 1; arr[1] == 2; arr[2] == 3; --->new Array(); var arr = new Array();//定义一个没有任何内容的数组对象,然后以下面的方式为其赋值 arr[0] = "arr0"; arr[1] = "arr1"; arr[2] = "arr2"; ---&

.NET(C#):在数组成员上加入XmlElement特性

原文 www.cnblogs.com/mgen/archive/2011/12/04/2276131.html 当对如下类进行XML序列化时: publicclassa {     publicint[] arr =newint[] { 1, 2, 3 }; }   结果会是: <axmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:xsd="http://www.w3.org/2001/XMLS

JS Array.slice 截取数组的实现方法_javascript技巧

slice定义和用法 slice() 方法可从已有的数组中返回选定的元素. 语法 arrayObject.slice(start,end) 参数 描述 start 必需.规定从何处开始选取.如果是负数,那么它规定从数组尾部开始算起的位置.也就是说,-1 指最后一个元素,-2 指倒数第二个元素,以此类推. end 可选.规定从何处结束选取.该参数是数组片断结束处的数组下标.如果没有指定该参数,那么切分的数组包含从 start 到数组结束的所有元素.如果这个参数是负数,那么它规定的是从数组尾部开始算

PHP对象转数组(Object转Array),Json转数组(Json转Array)的方法

(1)php对象转数组的方法(object 转 array): /** * object 转 array */ function object_to_array($obj){ $_arr=is_object($obj)?get_object_vars($obj):$obj; foreach($_arr as $key=>$val){ $val=(is_array($val))is_object($val)?object_to_array($val):$val; $arr[$key]=$val;

JS代码实例:遍历数组成员的迭代器

文章简介:实现一个遍历数组或对象里所有成员的迭代器. 实现一个遍历数组或对象里所有成员的迭代器. var each = function(obj, fn){         //+++++++++++答题区域+++++++++++                   //+++++++++++答题结束+++++++++++ };  try{                  var data1 = [4,5,6,7,8,9,10,11,12];         var data2 = {