美文网首页
C 语言之柔性数组

C 语言之柔性数组

作者: Zeaone | 来源:发表于2019-02-19 15:24 被阅读0次

一 历史

在c99标准出来之前。如果要在某个结构体中使用字符串变时,为了使字符串变量存储地址能与结构体整体连在一起,需要这样实现

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

typedef struct pen
{
    int len;
    char *data;//字符串变量
}pen;

int main(int argc, char **argv)
{
    char str[] = "this is a string";//需要填入的字符串
    /*
      动态申请一个pen类型结构体变量,
      它的大小为,pen类型的本身长度,
      再加上str(需要填入字符串的长度),再加1,
    */
    struct pen *p = (struct pen*)malloc(sizeof(pen) + strlen(str) + 1);
    p->data= NULL;
    //设置p的长度为目标字符串的长度
    p->len = strlen(str);
    
    
    /*
      将目标字符串拷贝到结构体对应的位置
      此处为什么p+1之后指向的是pen结构体存储空间后的位置,而不是只加一呢?
      因为此处的p+1偏移的是p指向类型大小的偏移量,什么意思呢?p指向的类型为pen类型的结构体,
      而pen类型的结构体大小为 len(4字节)加上 data(8个字节),由于此处有内存对齐的情况,
      所以实际上pen大小为 4 + 8 + 4(这个4为内存对齐的多余空间,如果再增加一个int类型的变量,
      pen的大小还是为16)=16字节
      所以此处p+1向后偏移了16字节,通过下方地址打印可以详细看出
     */
    strcpy((char*)(p + 1), str);
    //int所占字节数,不同机器不同。一般64位为4字节
    printf("sizeof(int): %ld\n", sizeof(int));
    //上文已说明,16字节
    printf("sizeof(pen): %ld\n", sizeof(pen));
    //起始地址
    printf("start: %p\n\n", (char*)p);
    //上文已说明,偏移后的地址
    printf("(p+1) : %p\n", (char*)(p+1));
    //偏移后,对应的字符串
    printf("(char*)(p+1): %s\n\n", (char*)(p+1));
    //结构体变量data的地址
    printf("&(p->data): %p\n", &(p->data));
    //数据,null,此处为空,故此变量已经被浪费。访问对应字符串数据需要(char *)(p+1)
    printf("p->data: %s\n\n", p->data);
}

二 柔性数组

通过上文我们可以看到,data字段是一个被浪费的指针(8个字节)。并且我们想取到结构体下的字符串变量时需要(char *)(p+1)写这么一串东西,既不好看,也容易出错,那有没有可以直接用p->data取到字符串并且内存是连续的,而且又不浪费data字段呢, 柔性数组 就是用来干这个的。

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

typedef struct pen
{
    int len;
    char data[];//柔性数组
}pen;

int main(int argc, char **argv)
{
    char str[] = "this is a new string";//需要填入的字符串
    struct pen *p = (struct pen*)malloc(sizeof(pen) + strlen(str) + 1);
    p->data= NULL;
    p->len = strlen(str);
   strcpy((char *)(p+1), str);
 printf("pen->data: %s\n", p->data);
}

C99使用不完整类型实现柔性数组成员,在C99 中,结构中的最后一个元素允许是未知大小的数组,这就叫做柔性数组(flexible array)成员(也叫伸缩性数组成员),但结构中的柔性数组成员前面必须至少一个其他成员。柔性数组成员允许结构中包含一个大小可变的数组柔性数组成员只作为一个符号地址存在,而且必须是结构体的最后一个成员,sizeof 返回的这种结构大小不包括柔性数组的内存 (此段话摘自:https://blog.csdn.net/ce123_zhouwei/article/details/8973073

相关文章

  • C 语言之柔性数组

    一 历史 在c99标准出来之前。如果要在某个结构体中使用字符串变时,为了使字符串变量存储地址能与结构体整体连在一起...

  • C++中的柔性数组

    描述 C99标准提供在结构体最后一个元素定义一个未知大小的数组,它就叫做柔性数组成员。 柔性数组的特点 定义柔性数...

  • C 实现链表的高速公路-跳跃表

    本文所需基础: 1.知道如何用c写链表。 2.下文将会教到的柔性数组。 预准备(柔性数组): 为了下文讲述方便,先...

  • 零长度数组与柔性数组

    零长度数组(Zero-length array)与柔性数组(Flexible array) GNU C允许使用零长...

  • C柔性数组和变长数组

    变长数组 C语言在C99以前,数组的维度必须是整数常量表达式, 而C99则做了很大改进,允许数组维度为整形变量或者...

  • iOS开发系列文章[转]

    C语言 iOS开发系列--C语言之基础知识 iOS开发系列--C语言之数组和字符串 iOS开发系列--C语言之指针...

  • C语言之数组

    数组: 为n个变量连续发配存储空间 所有的变量数据类型必须相同 所有变量所占的字节大小必须相等 数组初始化:完全初...

  • C 语言之数组

    一. 定义整型数组的方式 1. int array[5] = {0}; 给定数组元素个数,且赋值均为0 2. ...

  • C语言之数组

    1.一维数组 特点:同一数组中的所有元素都属于同种数据类型,数组元素用数组名和相应的下标来确定。方法:一个数组元素...

  • 再学C语言之指针要点

    C之字符数组 C之指针引用字符串 C语言之数组指针 数组指针:首先它是一个指针,它指向数组指针数组:首先它是一个数...

网友评论

      本文标题:C 语言之柔性数组

      本文链接:https://www.haomeiwen.com/subject/eqlxyqtx.html