0长度数组

来源:互联网 发布:mac如何airdrop 编辑:程序博客网 时间:2024/04/24 09:09
 0长度数组是个奇怪的东西, 下面的代码(两种形式之一)是可以通过编译的.
                char buf[];
   或者
                char buf[0];
   有什么用处呢? 大家知道数组名其实是数组所在内存的首地址, 那么0长度数组的名字,其实是在内存某个地方中作了一个标记, 在适合的时候将这个标记后面的一段内存作为这个数组的内容. 貌似数组下标溢出了,但是善于利用这点可以实现一个”变长”结构体.

例如下面的代码:



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

static const size_t def_name_len = 32 ;
typedef struct __Name
{
        size_t index;
        size_t len;
        char buf[0];
} Name, *PName ;

Name * createName(size_t index, const char * strname)
{
        size_t len;        
        PName pname = NULL;
        
        if (strname == NULL)
        {
                len = def_name_len;
               
        else
        {
                len = strlen(strname);
        }
        
        pname = (PName) malloc( sizeof(Name) + len + 1);  
        
        if(pname == NULL) return NULL;

        pname->index = index;
        pname->len = len;
        pname->buf[len] = '\0';
        if (strname)  strncpy(pname->buf, strname, len+1);
        return pname;
}

void freeName(PName pname)
{
        if(pname == NULL) return;
        free(pname);
        pname = NULL;
}

int main()
{
        int i;

        PName namelist[4] = {
                createName(1, "name1"),
                createName(2, "name2"),
                createName(3, "name3"),
                createName(4, "name4"),
        };
        
        for(i=0; i<4; ++i)
        {
                if(namelist[i])
                        printf("index %u \t name: %s \n", namelist[i]->index, namelist[i]->buf);
        }
        for(i=0; i<4; ++i)
        {
                freeName(namelist[i]);
        }
        return 0;
}
struct __Name有三个成员size_t index; size_t len; char buf[0]; 但是sizeof(Name)的结果是8, 为什么呢?因为上面说了,” 0长度数组的名字,其实是在内存某个地方中作了一个标记”, 所以不占空间, 上面代码中的pname = (PName) malloc( sizeof(Name) + len + 1);  一行,申请了一个Name结构体变量,然后这块内存后面紧跟了一块长len+1的内存,所以我们就可以用buf[0..len]来访问这段内存了. 图示如下:



CODE:-------------------------------------------------------------------------
 index (4byte) | len (4byte)  |<------- len+1 byte -------->|
-------------------------------------------------------------------------
| <----------Name-------------->|                    
                                |<-----buf[len+1] ------------|
    可见, 原理用一句话来总结,就是利用数组下标”故意”溢出来访问数组首地址后的内存.

0 0
原创粉丝点击