以下代码,根据我应该成功运行,但在运行时失败。我不明白原因:
void main()
{
int arr[5][3]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
int *m=arr[0];
int **p=&m;
p=p+1;
printf("%d",**p);
}
a.exe 在 gcc 编译器,windows 7 64 位运行时停止工作
以下代码,根据我应该成功运行,但在运行时失败。我不明白原因:
void main()
{
int arr[5][3]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
int *m=arr[0];
int **p=&m;
p=p+1;
printf("%d",**p);
}
a.exe 在 gcc 编译器,windows 7 64 位运行时停止工作
数组数组和指向指针的指针完全不同,不能互换使用。
例如,如果您查看数组arr
,它在内存中看起来像这样
+-----------+------------+------------+-----------+- ----+-----------+ | arr[0][0] | arr[0][1] | arr[0][2] | arr[1][0] | ... | arr[4][2] | +-----------+------------+------------+-----------+- ----+-----------+
当您拥有指针到指针p
时,程序并不真正知道它指向数组数组,而是将其视为指针数组,在内存中看起来像这样:
+------+------+------+------+ | p[0] | p[1] | p[2] | ... | +------+------+------+------+ | | | | | v | | 某物 | v | 某物 v 某物
所以当你做的时候p + 1
你得到p[1]
的显然是不一样的arr[1]
。
随着线
int **p=&m
您创建一个指向整数指针的指针。
然后,你在地址上加一——一个内存地址,也就是不是指向下一个整数的字节数的一倍。
然后你尊重它两次:
int **p=&m;
p
指向地址,m
放置在哪里:
... | m | sth | ... | p | ...
^ V
|_________________|
现在,增加它:
... | m | sth | ... | p | ...
^ V
|___________|
所以,现在p
指向sth
. 是什么sth
?没人知道。但是您正试图访问sth
包含的地址。这是未定义的行为。
在这里int **p=&m;
。p
指向m
. 那么当p = p + 1;
p 会指向m
(integer) 旁边的地址。该地址可能无法访问。