访问二维数组时 for 循环第二次迭代的访问冲突

Access violation on 2nd iteration of for loop when accessing a 2D array

我在 C 中有一个作业,用户必须在其中填充二维 grades[3][3] 数组。然后调用一个函数,该函数 returns 指向 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 中的监视菜单验证它在第一次迭代时运行良好,并且变量具有正确的值。但是,在第二次迭代中,它没有正常继续,而是在 curr_element = *(gradesPtr + i*3 + j); 行上抛出访问冲突错误。

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

这里有什么我遗漏的吗?

get_max 中,您执行:

int i, *max_addr = &i;

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

如果 if (curr_element > max) never 为真,max_addr 将永远不会 updated。该函数将 return 指向堆栈的 max_addr

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

如果数组的第一个元素(例如gradesPtr[0]又名grades[0][0])是最大值,

if将不成立 .

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

因此,您想要更改(无法编译):

*max_addr = gradesPtr + i * 3 + j;

进入:

max_addr = gradesPtr + i * 3 + j

max_addr 是一个 float * 但函数的 return 值是 int *。所以,我不确定这是如何编译的。

而不是:

int *max_addr = &i;

你想要:

float *max_addr = gradesPtr;

并且,您想将 return 值更改为 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;
}

由于您在函数中使用一维指针 并且 正在 returning 一个 指针 我们可以处理一维数组:

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;
}

grades为二维数组,应适当定义参数及return值

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
}