C 分配多个相同类型的数组
我需要分配几个相同类型和形状的数组。一开始,我做了如下工作:C 分配多个相同类型的数组,c,arrays,malloc,C,Arrays,Malloc,我需要分配几个相同类型和形状的数组。一开始,我做了如下工作: void alloc_arrays_v1(size_t nmemb) { int *a1, *a2, *a3; a1 = malloc(nmemb * sizeof int); a2 = malloc(nmemb * sizeof int); a3 = malloc(nmemb * sizeof int); /* do some stuff with the arrays */ f
void alloc_arrays_v1(size_t nmemb)
{
int *a1, *a2, *a3;
a1 = malloc(nmemb * sizeof int);
a2 = malloc(nmemb * sizeof int);
a3 = malloc(nmemb * sizeof int);
/* do some stuff with the arrays */
free(a1);
free(a2);
free(a3);
}
为了避免多次调用malloc
和free
,我将上述内容更改为:
void alloc_arrays_v2(size_t nmemb)
{
int *a, *a1, *a2, *a3;
a = malloc(3 * nmemb * sizeof int);
a1 = a;
a2 = a1 + nmemb;
a3 = a2 + nmemb;
/* do some stuff */
free(a);
}
这似乎还可以(从某种意义上说,函数在现实世界中的行为是相同的),但我想知道这是否仍然是有效的C代码(未定义的行为?),是否可以将此方法扩展到复杂的数据类型(结构数组等)。这两种方法都是有效的,因为您使用
malloc
分配连续内存。事实上,在C语言中建模矩阵时,经常使用与第二种情况形式类似的代码
值得注意的是
int a1, a2, a3, a4;
int* a = &a1;
int oops = *(a + 1);
是未定义的行为,因为您不能期望堆栈分配是连续的。它在C中完全有效。但请记住仅释放
a
指针。您的此方法类似于struct hack
然而,我认为该代码中的一个逻辑问题是,如果您超出a1
或a2
的范围,您将无法注意到它,因为您将访问有效的内存地址,即,您将不会出现Seg故障。然而,在第一种情况下,您“可能”得到SegFault并注意到您的错误。它完全有效 您所做的基本上与此相同:
void alloc_arrays_v1(size_t nmemb)
{
typedef int one_array[nmemb]; // this is one array
typedef one_array three_arrays[3]; // this are three arrays
one_array * a;
int *a1, *a2, *a3;
a = malloc(sizeof(three_arrays));
a1 = a[0]; // a[0] is a one_array, which decays into an int * here.
a2 = a[1]; // the same
a3 = a[2]; // as above
/* do some stuff with the arrays */
free(a);
}
不同的是,这里的计算是通过指针和数组算术来完成的。这是完全有效的C代码,是的,你可以用其他类型(包括结构)来完成(指针算术只要你允许就行,而且你让它很好)。在调试器中运行它,并对以
a
开头的地址进行计算,以确认这一点。@WhozCraig:我在现实世界中这样做:)不确定这与调试有什么关系,因为我调试了大量现实世界的代码。但看到它一行一行、一步一步地发挥作用是很有帮助的。不要认为调试器仅仅在发现bug方面是有帮助的;它们同样是检查有效代码并查看其在所选平台上如何工作的绝佳工具。sizeof int
-->,sizeof(int)
@BLUEPIXY:size of是一个运算符,而不是一个函数。你需要括号吗?谢谢你的精确。此外,它对结构是否仍然有效?超出其最大索引的阵列访问是未定义的行为-在这种情况下,而OPs案例绝不是UB。内存池就是这样工作的。完成最后一句话,或者更糟的是,你可能不会在第一个代码片段中得到一个segfault,因此不会注意到你的错误,这在许多观点(包括我的观点)中比崩溃更糟糕。更确切地说,这是等待中的崩溃,这从来都不是乐趣。在这两种情况下,都要小心指针的数学边界,你会没事的。@WhozCraig:谢谢你的拙见:-)我知道越界是UB,因此没有必要犯Seg错误,这就是为什么我要加上“may”。不管怎么说,正如您所说,我发现您自己对越界数组访问保持谨慎是正确的。