这是我康威的生命游戏C代码。
函数 newgen 检查相邻单元格,所有八个单元格,即使单元格位于矩阵的边缘。如何以不会导致访问超出绑定数据和未定义行为的方式更改它?
我也有这个错误:
1 IntelliSense: a value of type "void *" cannot be assigned to an entity of type "int *"
代码是:
void copy() {
int i, j;
for (i = j = 0; i < HEIGHT; i++) {
for (; j < WIDTH; j++) {
gb2[i][j] = gb[i][j];
}
}
}
void init() {
int i, j;
for (i = 0; i < HEIGHT; i++) {
gb [i] = malloc(sizeof(int)*WIDTH);
gb2[i] = malloc(sizeof(int)*WIDTH);
}
for (i = 0 ; i < HEIGHT; i++) {
for (j = 0 ; j < WIDTH; j++) {
gb [i][j] = 0;
}
}
gb[0][0] = 1;
gb[0][1] = 1;
gb[1][0] = 1;
gb[1][1] = 1;
copy();
}
... int main(){ int i; 在里面(); NEWGEN(); printg(); for(i = 0; i&lt; HEIGHT; i ++){ 自由(GB [I]); 自由(GB2 [I]); } }
答案 0 :(得分:1)
在newgen()
中,您从1循环到HEIGHT - 2循环,这样可以避免越界访问,但是对于从0循环到WIDTH - 2的列,所以每次都有超出范围的访问权限当你在第一列时,访问j - 1的行。即,
for (j = 0; j < WIDTH-1; j++) {
if (gb[i][j+1]) n++;
if (gb[i+1][j]) n++;
if (gb[i+1][j+1]) n++;
if (gb[i-1][j-1]) n++; // <- Here,
if (gb[i][j-1]) n++; // <- here,
if (gb[i-1][j]) n++;
if (gb[i+1][j-1]) n++; // <- ...and here.
if (gb[i-1][j+1]) n++;
当你开始循环遍历列时,以j等于1而不是0开始:
for (j = 1; j < WIDTH-1; j++) {
答案 1 :(得分:0)
我没有测试下面的代码(并且它仍然是不完整的)但你应该遍历数组中的所有元素并更新邻居计数。您可以使用几个遍历所有相邻单元格的循环,并在进行边界检查时执行边界检查。
开始处理每个单元格时,还应重置相邻单元格数。
void newgen()
{
for (int i = 0; i < HEIGHT; i++)
{
for (int j = 0; j < WIDTH; j++)
{
int n = 0;
for (int test_y = i - 1; test_y <= (i + 1); ++test_y)
{
for (int test_x = j - 1; test_x <= (j + 1); ++test_x)
{
if ((test_x != test_y) &&
(test_x >= 0) && (test_x < WIDTH) &&
(test_y >= 0) && (test_y < HEIGHT))
{
if (gb[test_y][test_x])
{
n++;
}
}
}
}
/* Process the n value here */
}
}
}
您可能只是使用静态数组而不是沿一个维度分配,或沿两个维度分配。目前它是静态和动态尺寸的混合,这不是一个问题,它似乎不一致。
您的Intellisense错误听起来像Intellisense只处理C ++代码,而不是C代码,但这只是猜测。你可以配置编译器(我假设MSVC在这里)编译为C或C ++,但也许Intellisense没有那个选项或者它是单独配置的。
答案 2 :(得分:0)
IntelliSense警告是因为您使用的是Visual C ++,并且该警告适用于C ++。 (当你使用C时,它不是那么“智能”。)你可以通过将malloc
的返回值转换为(int *)
来避免警告,尽管casting the return of malloc
is not recommended in C。
至于避免越界访问:不要访问越界。一些可能的解决方案包括:
创建一个函数来返回单个单元格的实时/死亡值,并检查那里的边界,如果它超出范围则返回0。 (或者你可以将网格环绕到另一边;如果你想要动画,例如在小网格上glider,这很好。)
不要在循环中包含第一行或最后一行或列,而应将其视为特殊情况,并且不要超出边界。
分配两个额外的行和列,将它们初始化为零,然后不迭代最后一行或列(即将您的活动网格视为[1..w] [1..h]但是分配w + 2列和h + 2行)。然后你不需要边缘的特殊情况,但使用少量的额外内存。