【问题标题】:Access violation on 2nd iteration of for loop when accessing a 2D array访问二维数组时,for 循环的第二次迭代出现访问冲突
【发布时间】:2022-01-16 15:31:59
【问题描述】:

我在 C 中有一个任务,用户必须填充一个 2D grades[3][3] 数组。然后调用一个函数,该函数返回指向main() 的指针,其中包含该数组中最大元素的地址。

所以,我定义了一个 int *get_max() 函数,其主体如下:

int *get_max(float *gradesPtr)
{
    int i, j, *max_addr = &i; //variable initialization
    float max = *gradesPtr, curr_element; //max gets the value of the 1st element in the array to not be empty

    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 3; j++)
        {
            curr_element = *(gradesPtr + i*3 + j); //(pointer + i*columns + j) formula used here
            if (curr_element > max)
            {
                max = curr_element; //get max element
                *max_addr = gradesPtr + i*3 + j; //get address of max element
            }
        }
    }

    return max_addr; //return "max_addr" to main
}

它是从main() 调用的,如下所示:

int *max_element = get_max((float *)grades);

代码似乎正确,因为我可以通过 Visual Studio 中的 Watch 菜单验证它在第一次迭代时运行良好,并且变量具有正确的值。但是,在第 2 次迭代中,它没有正常继续,而是在 curr_element = *(gradesPtr + i*3 + j); 行上引发访问冲突错误。

在调试了一下之后,似乎无论我如何将数组传递给函数(使用指向数组的指针或传递整个数组本身),也不管我如何将最大元素的地址保存到*max_addr(使用 (pointer + i*columns + j) 公式或 &amp;grades[i][j]),get_max() 函数将数组视为 一维数组而不是二维数组,从而引发访问冲突错误。在这里搜索提供了一些好看的解决方案,但它们不是我想要的。

这里有什么我遗漏的吗?

【问题讨论】:

  • max_element 是一个[简单] int,但get_max 返回int *(一个指针)。那么,这是如何编译的呢?
  • @CraigEstey 哎呀,我的错。 max_element是在原文件开头初始化的,我忘了把星号放在这里。

标签: c multidimensional-array access-violation


【解决方案1】:

如果grades是二维数组,则应适当定义参数和返回值

float *get_max(float gradesPtr[3][3])

现在不需要再做指针运算了,你可以简单地说

float *get_max(float grades[3][3])
{
    int i, j;
    float *max_addr = &grades[0][0]; //variable initialization
    float max = *max_addr;

    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 3; j++)
        {
            float curr_element = grades[i][j];
            if (curr_element > max)
            {
                max = curr_element; //get max element
                max_addr = &grades[i][j]; //get address of max element
            }
        }
    }

    return max_addr; //return "max_addr" to main
}

【讨论】:

  • 看来问题可能出在我初始化变量的方式上。感谢您帮助我!
【解决方案2】:

get_max 中,您可以:

int i, *max_addr = &i;

因此,max_addr [最初] 指向函数作用域变量 i

如果if (curr_element &gt; max)从不为真,max_addr 将永远更新。该函数将返回一个指向堆栈的max_addr

这是 UB(未定义行为),因为 i 超出范围。

if 将不为真如果数组的第一个元素(例如 gradesPtr[0] aka grades[0][0])是最大值。

而且,在if 中,您正在更改max_addr 指向的内容,而不是更新max_addr

所以,你想改变(不会编译):

*max_addr = gradesPtr + i * 3 + j;

进入:

max_addr = gradesPtr + i * 3 + j

max_addrfloat * 但函数的返回值是 int *。所以,我不确定它是如何编译的。

代替:

int *max_addr = &i;

你想要:

float *max_addr = gradesPtr;

并且,您想将返回值更改为float *


这是重构后的代码:

float *
get_max(float *gradesPtr)
{
    int i;
    int j;
    float *max_addr = gradesPtr;
    // max gets the value of the 1st element in the array to not be empty
    float max = *gradesPtr;
    float curr_element;

    for (i = 0; i < 3; i++) {
        for (j = 0; j < 3; j++) {
            // (pointer + i*columns + j) formula used here
            curr_element = *(gradesPtr + i * 3 + j);

            // get max element and address of max element
            if (curr_element > max) {
                max = curr_element;
                max_addr = gradesPtr + i * 3 + j;
            }
        }
    }

    return max_addr;
}

由于您在函数中使用一维指针并且返回一个指针,我们可以将数组视为一维:

float *
get_max(float *gradesPtr)
{
    float *max_addr = gradesPtr;
    float max_val = *max_addr;
    float *end_ptr = gradesPtr + (3 * 3);
    float *cur_ptr;

    for (cur_ptr = gradesPtr;  cur_ptr < end_ptr;  ++cur_ptr) {
        if (*cur_ptr > max_val) {
            max_val = *cur_ptr;
            max_addr = cur_ptr;
        }
    }

    return max_addr;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-15
    • 1970-01-01
    相关资源
    最近更新 更多