arrays - 为什么外循环中的malocs数量为10 * sizeof,内循环中为2 * sizeof?
问题描述
我不明白为什么我必须在外循环中使用 10 * sizeof 在内循环中使用 2 * sizeof?首先,我在两者上都使用了 1 * sizof(实际上只是 sizeof),但后来我在 valgrind(810)中出现了很多关于 8 等大小的错误。所以我玩了一些尺寸,发现 10 和 2是正确的尺寸。我怎样才能在未来计算出正确的尺寸而不是猜测?
#include <stdio.h>
#include <stdlib.h>
const int LOCATIONS = 9;
const int NUMBERS = 9;
typedef struct location {
int column;
int row;
int zone;
} location;
typedef struct Number {
int number;
struct location *lockNum[];
} Number;
int main(void) {
// Declare pointer to array structures Number.
struct Number * numbers[NUMBERS];
int i, j;
// Memory allocation for each structure Number of array.
for (i = 0; i < NUMBERS; ++i) {
// It happens to have 10 * sizeof to make it work without 0 errors in valgrind but why?
numbers[i] = (struct Number *) malloc (10 * sizeof(struct Number *));
// Initialize members of structure Number.
numbers[i]->number = 9;
// Allocate memory for each location whithin structure Number of array.
for (j = 0; j < LOCATIONS; ++j) {
// Same here but why 2 *?
numbers[i]->lockNum[j] = (struct location *) malloc (2 * sizeof(struct location *));
// Initialize members of structure location
numbers[i]->lockNum[j]->column = 0;
numbers[i]->lockNum[j]->row = 0;
numbers[i]->lockNum[j]->zone = 0;
}
}
// Do something...
// Print content of allocated spaces.
for (i = 0; i < NUMBERS; ++i) {
printf("\nThere are %d possible locations for number %d\n\n", numbers[i]->number, i + 1);
for (j = 0; j < LOCATIONS; ++j) {
printf("location %d at row %d column %d in zone %d\n", j + 1, numbers[i]->lockNum[j]->row, numbers[i]->lockNum[j]->column, numbers[i]->lockNum[j]->zone);
}
}
// Free memory after usage.
for (i = 0; i < NUMBERS; ++i) {
for (j = 0; j < LOCATIONS; ++j) {
free(numbers[i]->lockNum[j]);
}
free(numbers[i]);
}
return 0;
}
解决方案
这些mallocs的大小是一个刺。数据应基于底层类型的实际大小。唯一棘手的是允许 a 的灵活数组成员Number
。
灵活的数组成员通常使用结构的大小 + N * 数组元素类型的大小来分配。这可能会留下一些填充/松弛,但仍受支持。所以...
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
const int LOCATIONS = 9;
const int NUMBERS = 9;
typedef struct location {
int column;
int row;
int zone;
} location;
typedef struct Number {
int number;
struct location *lockNum[];
} Number;
int main()
{
struct Number *numbers[NUMBERS];
for (int i=0; i<NUMBERS; ++i)
{
numbers[i] = malloc(sizeof **numbers + (LOCATIONS * sizeof(location*)));
// Allocate memory for each location whithin structure Number of array.
numbers[i]->number = LOCATIONS;
for (int j = 0; j < numbers[i]->number; ++j) {
numbers[i]->lockNum[j] = malloc ( sizeof(location) );
// Initialize members of structure location
numbers[i]->lockNum[j]->column = j;
numbers[i]->lockNum[j]->row = i;
numbers[i]->lockNum[j]->zone = 42;
}
}
// print the results
for (int i=0; i<NUMBERS; ++i)
{
for (int j=0; j<numbers[i]->number; ++j)
{
printf("{%d %d %d} ",
numbers[i]->lockNum[j]->row,
numbers[i]->lockNum[j]->column,
numbers[i]->lockNum[j]->zone);
}
fputc('\n', stdout);
}
// free allocated spaces
for (int i=0; i<NUMBERS; ++i)
{
for (int j=0; j<numbers[i]->number; ++j)
free(numbers[i]->lockNum[j]);
free(numbers[i]);
}
}
输出
{0 0 42} {0 1 42} {0 2 42} {0 3 42} {0 4 42} {0 5 42} {0 6 42} {0 7 42} {0 8 42}
{1 0 42} {1 1 42} {1 2 42} {1 3 42} {1 4 42} {1 5 42} {1 6 42} {1 7 42} {1 8 42}
{2 0 42} {2 1 42} {2 2 42} {2 3 42} {2 4 42} {2 5 42} {2 6 42} {2 7 42} {2 8 42}
{3 0 42} {3 1 42} {3 2 42} {3 3 42} {3 4 42} {3 5 42} {3 6 42} {3 7 42} {3 8 42}
{4 0 42} {4 1 42} {4 2 42} {4 3 42} {4 4 42} {4 5 42} {4 6 42} {4 7 42} {4 8 42}
{5 0 42} {5 1 42} {5 2 42} {5 3 42} {5 4 42} {5 5 42} {5 6 42} {5 7 42} {5 8 42}
{6 0 42} {6 1 42} {6 2 42} {6 3 42} {6 4 42} {6 5 42} {6 6 42} {6 7 42} {6 8 42}
{7 0 42} {7 1 42} {7 2 42} {7 3 42} {7 4 42} {7 5 42} {7 6 42} {7 7 42} {7 8 42}
{8 0 42} {8 1 42} {8 2 42} {8 3 42} {8 4 42} {8 5 42} {8 6 42} {8 7 42} {8 8 42}
好的。这真的有效吗?修改原始代码以使用 5..10 中的随机数作为每个 Number 的位置数将是......有趣:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
const int NUMBERS = 9;
typedef struct location {
int column;
int row;
int zone;
} location;
typedef struct Number {
int number;
struct location *lockNum[];
} Number;
int main()
{
struct Number *numbers[NUMBERS];
srand((unsigned)time(NULL));
for (int i=0; i<NUMBERS; ++i)
{
int n_locations = 5 + (rand() % 6);
numbers[i] = malloc(sizeof **numbers + (n_locations * sizeof(location*)));
// Allocate memory for each location within structure Number of array.
numbers[i]->number = n_locations;
for (int j = 0; j < numbers[i]->number; ++j) {
numbers[i]->lockNum[j] = malloc ( sizeof(location) );
// Initialize members of structure location
numbers[i]->lockNum[j]->column = j;
numbers[i]->lockNum[j]->row = i;
numbers[i]->lockNum[j]->zone = 42;
}
}
// print the results
for (int i=0; i<NUMBERS; ++i)
{
printf("%d : ", numbers[i]->number);
for (int j=0; j<numbers[i]->number; ++j)
{
printf("{%d %d %d} ",
numbers[i]->lockNum[j]->row,
numbers[i]->lockNum[j]->column,
numbers[i]->lockNum[j]->zone);
}
fputc('\n', stdout);
}
// free allocated spaces
for (int i=0; i<NUMBERS; ++i)
{
for (int j=0; j<numbers[i]->number; ++j)
free(numbers[i]->lockNum[j]);
free(numbers[i]);
}
}
输出(显然不同)
7 : {0 0 42} {0 1 42} {0 2 42} {0 3 42} {0 4 42} {0 5 42} {0 6 42}
5 : {1 0 42} {1 1 42} {1 2 42} {1 3 42} {1 4 42}
7 : {2 0 42} {2 1 42} {2 2 42} {2 3 42} {2 4 42} {2 5 42} {2 6 42}
5 : {3 0 42} {3 1 42} {3 2 42} {3 3 42} {3 4 42}
6 : {4 0 42} {4 1 42} {4 2 42} {4 3 42} {4 4 42} {4 5 42}
10 : {5 0 42} {5 1 42} {5 2 42} {5 3 42} {5 4 42} {5 5 42} {5 6 42} {5 7 42} {5 8 42} {5 9 42}
9 : {6 0 42} {6 1 42} {6 2 42} {6 3 42} {6 4 42} {6 5 42} {6 6 42} {6 7 42} {6 8 42}
5 : {7 0 42} {7 1 42} {7 2 42} {7 3 42} {7 4 42}
10 : {8 0 42} {8 1 42} {8 2 42} {8 3 42} {8 4 42} {8 5 42} {8 6 42} {8 7 42} {8 8 42} {8 9 42}
无论原作者在做什么,都涉及赌博。上面的例子应该为你做你想做的事情提供了一个更好的方法。
推荐阅读
- performance - 有没有更好的方法在 MATLAB 中为类属性赋值?
- python - 在创建视图类中使用模型的先前数据存储在其他模型中
- angular - 当凭据在一端工作但在另一端不工作时如何修复 401 错误
- c - FFT 返回 NaN 值
- python - 如何在python中创建最小堆来存储边缘和重量
- javascript - React 基于 Web 的应用程序连接到物理硬件设备
- reactjs - 如何在 React 中创建水平时间线
- python - 从数组中删除 n 个连续元素,使剩余元素的幅度最小
- go - 将证书添加到 Postman 以连接到 Go 服务器
- flutter - 根据 Flutter 中应用的主题更改 AppIcon 的图像