我正在尝试重构我的代码以使其变得更好/更可读,因此我尝试更改2-D变量阵列分配,如下所示
// OLD CODE
int **map;
map = calloc(number, sizeof(int *));
if (!(map)) {
free(map);
return 1;
}
for (int i = 0; i < number; i++) {
map[i] = calloc(number, sizeof(int));
if (!(map[i])) {
while (--i >= 0) {
free(map[i]);
}
free(map);
return 1;
}
}
// NEW CODE
int (*map)[number] = malloc(sizeof (int[number][number]));
if (!(map)){
free(map);
return 1;
}
问题是,我使用MAP的所有功能都取得int **map
,并通过像我一样更改地图声明,而IDE告诉我incorrect type int[]* instead of int**
我应该使用什么代替int**
?在功能声明中使用int[]* map
告诉我can't resolve variable map
事实证明,以下代码不是C99替代方案 @m.m,而是GCC扩展。
无证GCC扩展:struct中的VLA
作为int (*map)[number] = malloc(sizeof (int[number][number]));
的替代方案,以简化代码,并保持与现有函数集的兼容性,将所需的所有内存分配给1 *alloc()
调用。
这确实要求,当使用map
完成代码时,所有内存都是用一个free(map)
免费的。此外,map[]
的单个行不再被重新分配,但可以交换在map[]
中。
int **map_allocate(size_t row, size_t column) {
struct {
int *ip[row]; // Array of pointers, followed by a ...
int i[row][column]; // 2D array of int
} *u;
u = calloc(1, sizeof *u);
if (u == NULL) {
return NULL;
}
for (size_t i = 0; i<row; i++) {
u->ip[i] = u->i[row];
}
return &u->ip[0];
}
注意:没有铸件和场i[][]
正确对齐。
与其他答案不同,将一个分配与标准代码不同,这有点棘手,因为一个人需要确保指示器的组合内存分配和int
需要在不寻常的情况下满足对齐的关注int
对齐要求的情况超过指针对齐。long long
如下。
如果这使"代码更易于阅读"留有OP的判断。
#include <stdlib.h>
#include <stdio.h>
long long **map_allocate_ll(size_t row, size_t column) {
long long **map;
long long *ints;
size_t pointers_sz = sizeof *map * row;
// extend pointer size to `*ints` boundary
pointers_sz = (pointers_sz + sizeof *ints - 1)/sizeof *ints * sizeof *ints;
size_t ints_sz = sizeof *ints * row * column;
printf("psize %zu, isize %zun", pointers_sz, ints_sz);
map = calloc(1, pointers_sz + ints_sz);
if (map == NULL) {
return NULL;
}
ints = (void*) ((char*) map + pointers_sz);
printf("map %pn", (void *) map);
for (size_t i = 0; i<row; i++) {
map[i] = &ints[i * column];
printf("map[%zu] %pn", i, (void *) map[i]);
}
return map;
}
int main() {
free(map_allocate_ll(5,3));
}
样本输出
psize 24, isize 120
map 0x80081868
map[0] 0x80081880
map[1] 0x80081898
map[2] 0x800818b0
map[3] 0x800818c8
map[4] 0x800818e0