假设我们要构造一个结构数组,其中在编译时无法知道结构的定义。
这是SSCCE:
#include <stdlib.h>
int main(int argc, char *argv[]){
if (argc < 3) return 1;
int n = atoi(argv[1]);
int k = atoi(argv[2]);
if ((n < 1) || (k < 1)) return 2;
// define struct dynamically
typedef struct{
int a[n];
short b[k];
}data_point_t;
int m = 10;
// construct array of `m` elements
data_point_t *p = malloc(sizeof(data_point_t)*m);
// do something with the array
for(int i = 0; i < m; ++i) p[i].a[0] = p[i].b[0] = i;
free(p);
return 0;
}
这适用于gcc
(C99
),但它不适用于clang
,这会产生:
error: fields must have a constant size:
'variable length array in structure' extension will never be supported
所以我显然依赖于gcc
扩展程序。我的问题是,如何处理标准符合C99
中的这类问题? (加分问题:如何在C++11
中执行此操作?)
注意:性能很重要,在迭代p
时,应该有对齐的内存访问权限。取消引用循环中的指针,产生随机内存访问,不是一种选择。
答案 0 :(得分:2)
我认为你最好的办法是放弃将数组包装在一个结构中的想法,咬紧牙关并自己分配一个2D数组。
这意味着您需要进行明确的索引编制,但无论如何都必须在幕后进行。
当谈到对齐时,如果你要访问每个n
数组中的每个m
数组元素,它可能无关紧要,最好使它们紧凑以最大化使用缓存。
类似的东西:
int *array = malloc(m * n * sizeof *array);
然后进行索引,只需执行:
// do something with the array
for(int i = 0; i < m; ++i)
{
for(int j = 0; j < n; ++j)
array[i * n + j] = j;
}
如果你非常担心这种乘法,请使用临时指针。当然,在分析它之后。
有时您会看到使用辅助宏来完成索引:
#define INDEX(a, n, i, j) (a)[(i) * (n) + (j)]
然后你可以把最后一行写成:
INDEX(array, n, i, j) = j;
它有点笨拙,因为n
当然需要一直进入那里。
答案 1 :(得分:1)
首先,在存在其他结构成员的情况下,将数组包装在结构中是唯一有意义的。如果没有其他struct成员,只需分配一个数组。
如果还有其他结构成员,则使用灵活数组成员来实现您的目标。灵活的数组成员在C标准中定义良好,并且适用于每个C99编译器。
// define struct dynamically
typedef struct{
type_t the_reason_you_need_this_to_be_a_struct_and_not_an_array;
int a[]; // flexible array member
}data_point_t;
// construct array of `m` elements
int m = 10;
size_t obj_size = sizeof(data_point_t) + n*sizeof(int);
data_point_t *p = malloc(m * obj_size);
答案 2 :(得分:0)
在C ++中,您当然可以像现在一样使用指针,但对于“适当的”C ++解决方案,唯一可行的解决方案是使用std::vector
:
struct data_point_t
{
explicit data_point_t(const size_t sz)
: a(sz) // Construct the vector `a` with `sz` entries,
// each element will be zero initialized (`int()`)
{}
std::vector<int> a;
};
int main(int argc, char *argv[]){
// Read `n`...
int n = 10; // Just example
// Read `m`...
int m = 10; // Just example
// Construct vector of `m` elements
std::vector<data_point_t> p(m, data_point_t(n));
// Here the vector `p` contains `m` elements, where each instance
// have been initialized with a vector `a` with `n` elements
// All fully allocated and initialized
// Do something with the array
// ...
}
这是有效的C ++ 03代码,所以除非你使用古老的东西(比如Turbo C ++),否则今天任何编译器都应该支持它。