码迷,mamicode.com
首页 > 编程语言 > 详细

柔性数组

时间:2019-08-04 19:18:47      阅读:118      评论:0      收藏:0      [点我收藏+]

标签:null   none   str   alt   指针成员   space   width   一个   理由   

介绍:

在日常的编程中,有时候需要在结构体中存放一个长度动态的字符串,一般的做法,是在结构体中定义一个指针成员,这个指针成员指向该字符串所在的动态内存空间,例如:

typedef struct test  
{  
       int a;  
       double b;  
       char *p;  
};

p指向字符串。这种方法造成字符串与结构体是分离的,不利于操作。如果把字符串跟结构体直接连在一起,不是更好吗?于是,可以把代码修改为这样:

char a[] = "hello world";
test *stpTest = (test )malloc(sizeof(test) + strlen( a ) + 1 );
strcpy(stpTest + 1, a );

      这样一来,( char* )(stpTest + 1 )就是字符串”hello world”的地址了。这时候p成了多余的东西,可以去掉。但是,又产生了另外一个问题:老是使用( char* )((stpTest + 1 )不方便。如果能够找出一种方法,既能直接引用该字符串,又不占用结构体的空间,就完美了,符合这种条件的代码结构应该是一个非对象的符号地址,在结构体的尾部放置一个0长度的数组是一个绝妙的解决方案。不过,C/C++标准规定不能定义长度为0的数组,因此,有些编译器就把0长度的数组成员作为自己的非标准扩展
鉴于这种情况就产生着以上这种结构(柔性数组):

typedef struct Test2
{
    int a;    4+4
    double b;  8
    char c; 1+7
    
    int p[0];   //0 //不占用结构体内存空间    //这个成员就叫做//柔性数组成员
};

void main()
{
    cout << sizeof(Test2) << endl;  //大小依然是24
}

当然类中也可以:

class Test1
{ 
//private:
public:
    //__vftp     //4
    double b;    //8

    int a;      //4
    char c[0];  //0
};

如果是下面这样的定义数组,那么编译会报错。

typedef struct Test2
{
    int a;    //4+4
    double b;  //8
    char c;    //1+3
};

void main()
{
    int p[0];
    cout << sizeof(Test2) << endl;
}

这个数组只能放在结构体最后一个成员上,不然放在结构体任何地方都会报错

typedef struct Test2
{
    //char c[0];    //这种情况也会出错
    int a;  
    //char c[0];    //这种情况会出错
    double b;  
};

理由:

如果定义在以上情况  ,那么c在定义的时候要虽然不开辟空间但是要保留自身的标记 ,如图举例:

技术图片

就会出现这这种情况图中整体是结构体内存,本来应该是b所标记的内存但因为c[0]的原因c与b的标记位置重复所以会出错,但是如果出现在最后一个成员上面就会不一样了。如图:

技术图片

因为最后一位成员这样不会为c开辟空间同时又保留了c的标记。

typedef struct Test2
{
    int a;    4+4
    double b;  8
    char c[0]; //0 //不占用结构体内存空间    //这个成员就叫做//柔性数组成员
};

void main()
{
    char str[]="hello CPP.";  
    Test2 t;
    cout<<t.c<<endl;
    cout << sizeof(Test2) << endl;  //大小依然是16
}

技术图片

图一

技术图片

图二

技术图片

图三

图一没有对c赋值但是c有值这就证明刚刚的内存图解释,当然并不是所有编译器中的内存块时连在一起的所以这种情况下不一定出现,也会出现乱码。如图二。图三就是图一可能性的内存图(意象图),这种情况只是解释说明小编不建议大家这样做,尽量按照下面的代码进行开辟空间。

用法:

#include<iostream>
#include<malloc.h>
using namespace std;

class Test1
{
public:
    virtual void fun()     
    {};
    virtual void fun1()
    {};
//private:
public:
    //__vftp     //4
    double b;    //8

    int a;      //4
    char str;    //1+3
    int  p[0];  //0
};

typedef struct Test2
{
    int a;    //4+4
    double b;  //8
    char c;    //1+7
    int p[0];   //0
};

void main()
{
    Test2 *text;
    text =(Test2*) malloc(sizeof(Test2)+sizeof(int)*10);
    for (int i = 0; i < 10; i++)
    {
        text->p[i] = i;
    }
    for (int i = 0; i < 10; i++)
    {
        cout << text->p[i]<<" ";
    }
    cout<< endl;
    free(text);
    text = NULL;
    cout << sizeof(Test2) << endl;

    Test1 *text1;
    text1 = (Test1*)malloc(sizeof(Test1) + sizeof(int) * 10);
    for (int i = 0; i < 10; i++)
    {
        text1->p[i] = i;
    }
    for (int i = 0; i<10; i++)
    {
        cout << text1->p[i]<<" ";
    }
    cout<<endl;
    free(text1);
    text1 = NULL;
    cout << sizeof(Test1) << endl;
}

技术图片

柔性数组尽量在结构体中使用(类很少虽然可以但是类数据成员大部分为私有)

区别:

typedef struct node
{
    int len;
    int a[];//或者写成int a[0];
}node;

以上结构体中a就是所谓的柔性数组,柔性数组在C99标准中已经加入。柔性数组即大小不确定的数组,放在结构体最后。

首先需要知道的是,sizeof(node)=4;不论是否给柔性数组后面的a分配了多少空间,sizeof(node)的值不变,均为4。并且,柔性数组只能出现在结构体中的最后一个变量上。若结构体中只有一个变量,则不能开创柔性数组,即不能开创下面这种柔性数组:

struct ss
{
   char b[];//数组类型并不一定限定于int、char等
};
 
柔性数组和以下这种方式有什么区别呢?
typedef struct node1
{
     int len;
     int *a;//int *a可不需要放在结构体最后
}node1;

首先sizeof(node1)=8而sizeof(node)=4。

并且如果要对node1中的a进行开创空间的步骤是:

node1 *k;

k=(node1 *)malloc(sizeof(node1));//首先给k开创node1大的空间

k->a=(int *)malloc(sizeof(int)*50);//给k->a开创50个int大的空间

最后释放空间的方式:free(k->a);free(k);

而对node开创同样大的空间方式是:

node *k;

k=(node *)malloc(sizeof(node)+50*sizeof(int));//向柔性数组a分配了50个int大小的空间

最后释放空间的方式为:free(k);

柔性数组

标签:null   none   str   alt   指针成员   space   width   一个   理由   

原文地址:https://www.cnblogs.com/ycw1024/p/11299030.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!