它是有效的内联由过度分配内存的结构变长数组?

问题描述 投票:2回答:1

我有想保持在连续的存储器,这样我可以能够memcpy整个结构等,但是我的结构包含可变长度的阵列的结构。现在,这个长度将被固定程序执行的时间,但在编译的时候它是未知的。我能解决这个问题通过在结构,以腾出空间阵列以下分配内存?

所以,如果我开始

struct license_plate{
    char issuing_province_territory_code [2];
    char* number;
}

我需要为malloc单独number,所以我认为做以下的

struct license_plate_v2 {
    char issuing_province_territory_code [3];
    char number[1];
}

并分配它是这样

size_t sizeof_license_plate_v2( int number_length ){
    return sizeof(struct license_plate_v2) + number_length * sizeof(char);
}


struct license_plate_v2* malloc_license_plate_v2( int number_length ){
    return malloc( sizeof_license_plate_v2( number_length ) );
}

然后能够迭代数组像

struct license_plate_v2* index_license_plate_v2( struct license_plate_v2 *arr, int index, int plate_num_len ){
    return  arr + index * sizeof_license_plate_v2(plate_num_len);
}

void print_all( struct license_plate_v2* plates, int num_of_plates, int plate_num_len ){
    for( int plate_index = 0; plate_index < num_of_plates; plate_index++ ){
        struct license_plate_v2* plate = index_license_plate_v2( plates, plate_index, plate_num_len );
        printf( "where: %s, plate: %s\n", plate->issuing_province_territory_code, plate->number  );
    }
}

这是有效的C?这是保证工作或我使用的是未定义的行为?是否有与字节对齐的任何问题,如果阵列结构的?是否有此一学期?这是实现这种效果的正确方法?

这似乎工作:

#include <stdlib.h>

int main( int argc, char** argv ) {
    //these values could have from from argv for example
    int num_len = 7;


    struct license_plate_v2 *arr = malloc( 4  * sizeof_license_plate_v2(num_len) );

    struct license_plate_v2 *arr_0 = arr + 0 * sizeof_license_plate_v2(num_len);
    memcpy( arr_0->issuing_province_territory_code, "ON"      , 3           * sizeof(char) );
    memcpy( arr_0->number                         , "BFKK281" , (num_len+1) * sizeof(char) );

    struct license_plate_v2 *arr_1 = arr + 1 * sizeof_license_plate_v2(num_len);
    memcpy( arr_1->issuing_province_territory_code, "ON"      , 3           * sizeof(char) );
    memcpy( arr_1->number                         , "BYTR741" , (num_len+1) * sizeof(char) );

    struct license_plate_v2 *arr_2 = arr + 2 * sizeof_license_plate_v2(num_len);
    memcpy( arr_2->issuing_province_territory_code, "ON"      , 3           * sizeof(char) );
    memcpy( arr_2->number                         , "CAAA224" , (num_len+1) * sizeof(char) );

    struct license_plate_v2 *arr_3 = arr + 3 * sizeof_license_plate_v2(num_len);
    memcpy( arr_3->issuing_province_territory_code, "ON"      , 3           * sizeof(char) );
    memcpy( arr_3->number                         , "CASD431" , (num_len+1) * sizeof(char) );

    print_all( arr, 4, 7 );

    free( arr );   
}

PS-这是一个简单的例子来说明这个问题,现实世界中的问题涉及到的东西就像高达数百万的位置与上千种(运行但不编译时间常数)数据点每一个都是一个结构不是char的,所以一些显而易见的变通并不适用。

c arrays struct var undefined-behavior
1个回答
5
投票

具有柔性阵列构件结构不能是数组的元素。这是决定在C standard的部分6.7.2.1p3:

结构或联合不得含有与构件不完整或功能类型(因此,一个结构不得含有自己的一个实例,但也可以包含一个指向自己的一个实例),不同之处在于结构的最后一个成员具有多于一个名为构件可以具有不完整的数组类型;这样的结构(和含有,可能递归任何结合,一个构件是这样的结构)不得结构的部件或阵列的元件

这样做的原因是,数组索引是通过指向是该结构的大小的倍数的存储器位置来完成。但是,如果该结构具有可变大小,有没有办法知道一个结构的下一个实例位于内存中。

在您的特定情况下,一辆车牌号的最大长度是没有那么大,所以只使用固定大小足以容纳它可能包含任何值。

struct license_plate{
    char issuing_province_territory_code[3];
    char number[20];
}

此外,您还成立了一个灵活的数组成员大小为1的数组的方式是这样做,他们的标准化之前的老办法,它常常被称为“结构体黑客”。声明一个柔性阵列构件的现代方法是用一个未指定大小:

struct license_plate_v2 {
    char issuing_province_territory_code [3];
    char number[];
}

sizeof(struct license_plate_v2)不包括flexible array member

© www.soinside.com 2019 - 2024. All rights reserved.