【发布时间】:2019-07-05 01:46:59
【问题描述】:
我有一个结构,我想保留在连续的内存中,这样我就可以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-这是一个简单的例子来说明这个问题,现实世界的问题涉及到数百万个位置,具有数千个(运行但不是编译时间常数)数据点,每个数据点都是一个结构而不是 @987654329 @,所以一些明显的变通方法不适用。
【问题讨论】:
-
在上面的示例代码中
num_len不应该是7吗? -
是的。我现在已经修好了。
-
对齐会是个问题。即使您在
struct中显示的两个成员都是char的数组,并且(根据C 标准)要求char具有最弱的对齐,但结构本身可能具有更高的对齐要求。 C 要求所有指向结构的指针具有相同的表示形式,而 C 实现可能会选择通过要求所有结构具有某种最小对齐来部分满足这一点。 -
这被称为“结构黑客”并且没有明确定义。您正在寻找灵活的数组成员。
-
@Lundin: struct hack 被明确定义并得到绝大多数实现的支持,并被许多程序所依赖,使用 C89 标准编写的预先存在的语言描述。鉴于标准委员会的章程,他们可能打算将其视为他们提到的“流行扩展”之一,支持将是“实施质量”问题,尽管许多实施可能没有特别认为持续支持因为已经明确定义的东西实际上是“扩展”。
标签: c arrays struct var undefined-behavior