假设我有个函数 foo:
void foo(char ***buff, int size) {
for(int i = 0; i != size; i++){
for(int j = 0; j != size; j++) {
(*buff)[i][j] = 'a';
printf("%c\t", (*buff)[i][j]);
}
printf("\n");
}
}
如果我给它传入一个动态 2d 数组的地址,一切安好:
int main(){
static int size = 3;
char **eg = (char**)malloc(size * sizeof(char*));
if(eg != NULL){
for(int i = 0; i != size; i++){
eg[i] = (char*)malloc(size * sizeof(char));
if(eg[i] == NULL){
for(int j = 0; j != i; j++)
free(eg[j]);
free(eg);
exit(1);
}
}
foo(&eg, size);
}
return 0;
}
但是如果我给它传入一个固定大小的 2d 数组的地址时,就报 seg fault 了:
int main(){
static int size = 3;
char eg2[size][size];
foo(&eg2, size);
return 0;
}
请问哪里出了问题?
1
innoink 2018-04-19 08:11:05 +08:00 via Android 1
因为数组名取地址并不是你想的那个结果
|
2
gnaggnoyil 2018-04-19 08:16:04 +08:00 3
C 语言标准中只允许 T []的左值到 T *右值的转换,因此 char [][]和 char **没有五毛钱关系.换句话说,char (*)[][]和 char ***所指向的类型是 incompatible 的,强行指向同一个对象的后果是未定义行为.C++中 implicit conversion 的要求更严格,char (*)[][]强转 char ***的结果是 ill-formed.
array to pointer decay 真是害死人啊(叹气 |
3
tempdban 2018-04-19 08:16:49 +08:00 1
*(buff+i*size+j) = 'a';
|
4
ghostheaven 2018-04-19 08:30:41 +08:00 via Android 1
二维数组是一个连续的内存空间,可以当成 NxN 的一维数组来看。数组指针的方式相当于第一维保存的是指针,指向每个第二维的数组开头。
|
5
omph 2018-04-19 08:34:28 +08:00 1
```C
#include <stdio.h> int main(){ char eg2[3][3] = {0}; char ***q = &eg2; printf("eg2=%p\n", eg2); printf("q=%p\n", q); printf("*q=%p\n", *q); printf("**q=%p\n", **q); return 0; } ``` |
6
owt5008137 2018-04-19 08:47:25 +08:00 via Android
因为内存结构不一样
|
7
Danswerme 2018-04-19 08:59:15 +08:00 via Android 1
惊了,我才发现居然有 C++节点
|
8
heiher 2018-04-19 09:54:34 +08:00 1
其实在写动态分配版时就应该能发现问题呀,eg2[size][size] 对应的内存里怎么会有地址呢?
|
9
wizardoz 2018-04-19 10:06:52 +08:00 1
数组地址是常量,为啥要作为三指针传?
另外,好像对数组名取地址还是一样的地址,所以你传进去的指针实际差了一层。 |
10
wizardoz 2018-04-19 10:08:37 +08:00
你这样试试看?
int main(){ static int size = 3; char eg2[size][size]; char** tmp = eg2; foo(&tmp, size); return 0; } |
11
acros 2018-04-19 10:10:25 +08:00 1
C 不熟了····
只记得二维数组没出现过三个***的,但一时间没找到问题,看了楼上回复才恍然大悟。 |
12
araraloren 2018-04-19 13:12:29 +08:00 1
...
... Your index has out of bound! |
13
picasso2501 2018-04-19 13:22:31 +08:00 1
a[M][N] 是 a[M*N]的语法糖
|
14
seancheer 2018-04-19 19:48:06 +08:00 1
只传过一维的,不会有问题,二维的没试过。。不过楼上大佬说的对,c 里面数据和指针并不是一个东西。
|
15
hackpro 2018-04-20 10:14:05 +08:00 1
@heiher #8 C99 之后 VLA 支持推迟到运行时
@xzpjerry731 实际上你的问题在于:(*buff)[i][j] = 'a'; buff 解引用之后是个 char ** 你这里直接用数组下标操作符[i] 相当于偏移一个 MACHINE WORD 所以 @gnaggnoyil #2 说 [] -> * 一般没啥问题 反过来要掂量掂量 |