是我正在尝试运行的代码
#include <iostream>
using namespace std;
int foo(int **a){
cout<<*(a+3)<<endl;
return 1;
}
int main(){
int a[2][2] = {{1,2},{3,4}};
std::cout << sizeof(a);
foo((int **)a);
}
当我在这个数组中有四个元素时,不应该将值*(a + 3)返回值4,而不是返回一个地址,当我尝试取消引用该地址时(即**(a +) 3))我得到段错11
答案 0 :(得分:6)
实际上,您正在定义一个整数数组。它可以衰减为指向整数数组的指针,但它不会衰变为整数指针的pointe。
如果你绘制内存布局会有所帮助:
+---------+---------+---------+---------+
| a[0][0] | a[0][1] | a[1][0] | a[1][1] |
+---------+---------+---------+---------+
| 1 | 2 | 3 | 4 |
+---------+---------+---------+---------+
如果你让它衰变成一个指向数组的指针:
int (*pa)[2] = a;
+---------+---------+---------+---------+
| pa[0] | pa[1] |
+---------+---------+---------+---------+
| 1 | 2 | 3 | 4 |
+---------+---------+---------+---------+
请注意sizeof(*pa) = 2 * sizeof(int)
的方式。这些值中的每一个都可以衰减为指向整数的指针,但绝不会指向指向指针的指针:
int *p = pa[0];
无论如何,您可以将衰减的指针指向整数数组转换为指向整数的指针并直接访问这四个值:
int *p = (int*)a;
std::cout << p[3] << std::endl;
std::cout << *(p + 3) << std::endl;
记忆将是这样的:
+---------+---------+---------+---------+
| p[0] | p[1] | p[2] | p[3] |
+---------+---------+---------+---------+
| 1 | 2 | 3 | 4 |
+---------+---------+---------+---------+
但是如果你将它转换为int**
,你会得到毫无意义的值,因为在内存中没有指针,只有整数。
答案 1 :(得分:2)
数组不是指针。是的,它可以衰减到一个并不意味着它是一个指针。如果要传递二维数组,则可以使用
int foo(int a[][2]);
或者如果你想采用任何大小的数组,那么你可以使用
template<std::size_t N>
int foo(int a[][N]);
答案 2 :(得分:0)
取消引用int**
后,您获得int*
。但是,您要取消引用值4
的位置,该位置被解释为int*
。这就是为什么cout打印0x4
,因为它将其格式化为地址。尝试将int*
作为参数:
#include <iostream>
using namespace std;
int foo(int *a){
cout<<*(a+3)<<endl;
return 1;
}
int main(){
int a[2][2] = {{1,2},{3,4}};
std::cout << sizeof(a);
foo((int *)a);
}
然后打印4。
这只是一个如何修复这段代码的例子,并不是正确的做事方式。另外正如@rodrigo在他的回答的评论中所述,如果int的大小不等于其指针的大小,这是行不通的。我只想告诉你为什么你认为它是在打印一个地址 - 因为它被解释为一个。
答案 3 :(得分:0)
你的解除引用太远了。 a已经指向数组中的第一个元素。所以** a将数组中的第一个值视为地址而不是值。试试
foo((int *)a)