我尝试调试以下代码,并且我得到了一个"访问冲突"错误。我不明白为什么第二个循环在访问第二行元素时失败,而第一个循环能够访问所有元素。
我弄乱了*
,&
和[]
,但无法弄明白。
感谢。
#include <iostream>
void a(const int* data, unsigned int nElements, unsigned int nColumns) {
for (unsigned int i = 0; i < nElements; ++i)
std::cout << data[i];
for (unsigned int i = 0; i < nElements / nColumns; ++i)
for (unsigned int j = 0; j < nColumns; ++j)
std::cout << (&data)[i][j];
}
int main() {
int arr[2][5] = {
{ 0, 1, 2, 3, 4 },
{ 5, 6, 7, 8, 9 }
};
a(*arr, 2 * 5, 5);
return 0;
}
答案 0 :(得分:2)
(&data)[i]
显然是假的。 data
是一个不是数组的变量。编写(&data)[0]
并将变量视为具有一个元素的数组是合法的。但是,如果i > 0
然后您尝试在存储data
之后访问内存,那么这不是您拥有的任何内存。 (不要将指针data
与它指向的东西混淆)。
您正在寻找的语法是:
std::cout << data[i * nColumns + j];
这个*
当然是乘法,而不是取消引用算子。在调用此功能时,您正在&#34;展平&#34;数组通过将其视为10元素1-D数组,因此您需要使用算术来计算所需的索引。
最后,在函数调用中,*arr
应为(int *)&arr
或(int *)arr
。你实际写的是arr[0]
,它是一个5元素的数组。它是一个超出界限的访问权限,可以尝试从函数中读取超过5个元素。实际上,由于效率原因,编译器不会尝试检测越界访问,它似乎会起作用。
答案 1 :(得分:1)
*arr
等于*(arr + 0)
,等于arr[0]
。 arr[0]
只有5 nElements
,而不是10.请按以下方式调用函数:
a(*arr, 5, 5);
答案 2 :(得分:1)
将double for循环中的行更改为:
std::cout << data[i * nColumns + j];
答案 3 :(得分:0)
一旦进入a
函数,就丢失了所有类型信息,因此您不能指望下标运算符可以正常工作,因为您没有说明数组的大小。在参数列表中指定大小,下标将起作用:
void a(int const (&data)[2][5]) {
for (auto const& row : data)
for (auto i : row)
::std::cout << i << " ";
::std::cout << ::std::endl;
}
然后,您甚至可以疯狂地将原型更改为:
template <size_t R, size_t C>
void a(int const (&data)[R][C]) {
因此它适用于所有2D阵列。