【问题标题】:c define arrays in struct with different sizesc 在struct中定义不同大小的数组
【发布时间】:2013-07-30 20:25:07
【问题描述】:

我需要为两种类型的对象定义一个结构。两者具有完全相同的数据结构并执行相同的任务(成员方法)。

唯一的区别是两种类型的数组大小不同,一种使用SIZE_A,另一种使用SIZE_B。

不希望重复结构和函数的定义。

我怎样才能使用一种类型的“结构”,并用不同的大小初始化它的数组?

#define SIZE_A 100
#define SIZE_B 200

typedef struct{
  int matr[SIZE_A][SIZE_A];  // for another type matr[SIZE_B]
  int arr[SIZE_A];           // for another type arr[SIZE_B]
  int size;                  // will be initialized to SIZE_A or SIZE_B
  int var1, var2;
}s;

void task1(s* si){
  ...
}

void task2(s* si){
  ...

【问题讨论】:

  • 内存不连续你关心吗?
  • 不,没有特殊限制。

标签: c struct


【解决方案1】:

即使使用联合,结构也将与两个数组中最大的一样大。

执行以下操作之一:

  1. 忽略最大数组大小的开销。 (使用一个数组或联合)
  2. 为每种类型创建一个单独的结构。
  3. 使用malloc 动态分配数组。

【讨论】:

  • 我想选择'2',但这意味着我也必须复制函数,例如:void task1(struc_a* s); void task1(struct_b* s), ... 有很多任务,所以复制它们是不好的。这让我想到使用选项“1”和“3”。
  • @lukmac 正确,除非差异很大,否则我建议 1. 如果它很大,也许 3. 也可以。
【解决方案2】:

我会将matr 设置为结构末尾的灵活数组。然后,我会将arr 数组粘贴到matr 的最后一行。

typedef struct {
    int size;
    int var1, var2;
    int matr[];
} s;

static inline int size_ok_s (int size) {
    switch (size) {
    case SIZE_A:
    case SIZE_B:
        return 1;
    default:
        break;
    }
    return 0;
}

s * create_s (int size) {
    s *x = 0;
    if (size_ok_s(size)) {
        x = malloc(sizeof(*x) + sizeof(int[size+1]));
        if (x) x->size = size;
    }
    return x;
}

要实现统一的界面,可以使用宏:

#define s_matr(x) ((int (*)[(x)->size])(size_ok_s((x)->size) ? (x)->matr : 0))
#define s_arr(x)  (s_matr(x)[(x)->size])

所以,要访问s *foomatrith 行和jth 列,以及它的karr 的>th 元素:

s *foo = create_s(SIZE_A);
/* ... */
    s_matr(foo)[i][j] = 0;
    s_arr(foo)[k] = 0;

灵活的数组成员是第 6.7.2.1 节 ¶16 中描述的 C.99 的新特性。在 C.99 之前,C 程序员经常使用所谓的 struct hack

typedef struct {
    int size;
    int var1, var2;
    int matr[1];
} s;

s * create_s (int size) {
    s *x = 0;
    if (size_ok_s(size)) {
        x = malloc(sizeof(*x) + sizeof(int[size]));
        if (x) x->size = size;
    }
    return x;
}

这是一个 hack,因为在 C.89-90 中,使用大于 0 的值索引 matr 数组在技术上是访问超出其边界的对象。然而,这是一种常见的做法,并且可以广泛移植。 C.99 正式认可了具有灵活数组成员的机制,尽管它需要在数组声明中不指定大小的语法。

【讨论】:

    【解决方案3】:

    让数组成为指针并根据需要分配给它们(适当的大小)。只有缩小尺寸是访问二维数组会有点笨拙。

    【讨论】:

    • “让数组成为指针”有点误导。数组不是指针。
    • 由于数组元素只是数组基地址的偏移量,因此将“数组”(而不是第一个元素)仅视为基地址并不是不合逻辑的。换个说法,将地址存储在大小为elements * sizeof(type)malloced 数组中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-27
    • 2010-12-30
    • 1970-01-01
    • 1970-01-01
    • 2018-02-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多