访问二维数组时 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
}
我在 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
超出范围。
如果数组的第一个元素(例如 并且,在 因此,您想要更改(无法编译): 进入: 而不是: 你想要: 并且,您想将 return 值更改为 这是重构后的代码: 由于您在函数中使用一维指针 并且 正在 returning 一个 指针 我们可以处理一维数组: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;
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;
}
若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
}