且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

C99 flexible array number 伸缩型数组成员

更新时间:2022-08-14 15:20:19

这种特性用来射你那个结构体中最后一个成员是特殊成员,它是不存在的
它包含如下规则:
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;
这种方式就不连续的,比较麻烦。