这不是一个问题,“如何将其传递给函数?”但是,“这可以接受吗?”
void func( int **ptr );
int main( int argc, char* argv[] )
{
int arr[][3] = {{1, 2,}, {3, 4}, {5, 6}};
int *pArr = *arr;
(&pArr[0])[1] = 3;
func(&pArr);
cin.get();
return 0;
}
void func( int **ptr )
{
cout << "In func()" << endl;
ptr[0][1] = 5;
}
据我所知,这是有效的。它对我来说并不是很安全,但我更喜欢将2D数组传递给函数。而是一个为我工作的指针。
对于那些必须阅读我的代码的人来说,这会非常混乱吗?我应该使用其他方法吗?使用指向数组的指针是一个坏主意吗?
另外,质疑一点偏离主题。我为什么要写:
int arr[] = { 1, 2, 3, 4, 5 };
int *pArr = *arr;
但为什么我不能写
int arr[][3] = {{1, 2,}, {3, 4}, {5, 6}};
int *pArr = **arr;
甚至使用** pArr?
答案 0 :(得分:6)
你在这里感到困惑。 int arr[][3] = {{1, 2,}, {3, 4}, {5, 6}};
是不指向长度为3的数组的指针。它是一个单个固体内存块9 int
s长,它会衰减为单个int*
。编译器为您的单个内存块执行3 * first + second映射。
函数中的下标无效的原因是因为函数无法确定数组的维数。使用单维数组,您不需要此信息 - 您只需将索引添加到给定的基指针。但是,对于二维数组,您需要维度来计算最终索引。
您的函数中的 ptr[0][1] = 5;
正在被翻译为*((*(ptr + 0)) + 1) = 5;
,这显然不是您想要的arr
不是指针数组。
编辑:回应评论:
ptr [0] [1]会覆盖数组[0] [1]中的信息
是的,你在这里很幸运 - 这就是原因。将数组传递给函数时,传递了(&pArr[0])[1]
,它是指向数组第一个元素的指针。当您执行*((*(ptr + 0)) + 1) = 5;
时,ptr+0
成为无操作,离开*(*ptr + 1) = 5;
,根据您的输入数据,它确实具有明确定义的行为(它将arr
视为单个 - 维数组)。但是,如果你试图改变下标的第一个维度,它就会爆炸。
答案 1 :(得分:4)
让我们仔细剖析一下,因为数组到指针的转换有时会令人困惑。
int arr[][3] = {{1, 2,}, {3, 4}, {5, 6}};
arr
现在是一个包含3个整数的3个数组的数组。
int *pArr = *arr;
*arr
在表达式中使用数组arr,因此它衰减到指向arr的第一个元素的指针 - 指向3个int数组的指针(包含{1,2,0}的数组)。取消引用该指针(使用*
)可以得到3个整数的数组。现在你在表达式中使用那个数组,它衰减到指向int的指针,指向pArr。
(&pArr[0])[1] = 3;
pArr[0]
给出pArr指向的整数(数字1)。 &pArr[0]
指向该整数(实际上等于pArr)。使用[1]索引指针会引用数字1之后的下一个整数,即数字2.对于该引用,您将分配3.这是catch:指向数组元素的指针只能用于访问同一数组的其他元素。你的指针指向数组{1,2,0}的一个元素,你已经改为{1,3,0},这很好,但是
func(&pArr);
现在你正在创建一个指向int指针的指针(因为pArr是指向int的指针),并将其传递给你的函数。
ptr[0][1] = 5;
现在你已经使用了ptr[0]
,它计算了指向对象,这是你的原始指针pArr。这一行相当于pArr[1] = 5;
,这仍然有效(将{1,2,0}数组更改为{1,5,0})。但是,ptr[1][...
将无效,因为 ptr未指向任何类型的数组。它指向一个独立的指针。增加ptr将使其指向未初始化的内存并且取消引用将是未定义的行为。
还有其他问题:
你不应该写这个:
int arr[] = { 1, 2, 3, 4, 5 };
int *pArr = *arr;
数组arr
衰减到指向int的指针(指向数字1),取消引用给出整数,并且不能将整数赋给指针pArr。 gcc说错误:从'int'无效转换为'int '*。
同样,你不能这样写:
int arr[][3] = {{1, 2,}, {3, 4}, {5, 6}};
int *pArr = **arr;
出于同样的原因:* arr是3个整数的数组{1,2,0},** arr是整数1,并且不能将整数赋给指针。
答案 2 :(得分:-1)
我发现C ++中的多维数组总是有点令人困惑,并且往往会避免它们。有几种解决方案更容易理解,例如Boost.MultiArray或Boost.UBlas库中的类,或矢量矢量,这取决于您的需求。