让我们考虑以下C代码:
char matrix[10][10];
char** array;
array = matrix;
printf("%c", array[2][3]);
我在第array = matrix
行发出警告:assignment from incompatible pointer type
我想这是因为第一个数组已经静态声明,第二个数组已经动态声明,但真正的问题出在printf
行。该程序简直崩溃
我似乎无法使用char**
运营商访问[][]
我该如何解决这个问题?
注意:我稍微简化了上下文。在原始程序中,array
是通过函数分配的,该函数的返回类型为char**
,但实际上返回char[10][10]
。
答案 0 :(得分:1)
char array[10][10]
不会衰减为char**
而是char*
。多维数组在内存中是连续的,但是char**
是指向指针的指针,意味着每个'行'不能保证在记忆中彼此相邻。
即array[10][10]
在内存中看起来像这样
&array (type char*)
|
| (points to)
|
\/
|---row/array one of length 10 chars---|---row/array two of length 10 chars---|...|---row/array ten of length 10 chars---|
与
没有什么不同&array (type char*)
|
| (points to)
|
\/
|---array of length 100 chars---|
所以它或多或少像char[100]
但只是以不同方式访问。
另一方面,char** p2p
可以像
p2p (type char **) (points to array of pointers which is contiguous in memory)
|
| (points to)
|
\/
|---pointer to first row of chars---|---pointer to second row of chars---|...
| |
| (points to) | (points to)
| |
\/ \/
|****************|--row/array of chars--|*************|-- row/array of chars--|********
其中***
是未知大小的任意位内存。实际上,并不能保证最后一组数组完全按照任何特定的顺序排列,更不用说它们彼此相邻了(即最后一组箭头可以相互交叉。
答案 1 :(得分:1)
char**
与char[10][10]
不同。当我们展示char**
如何存储在内存中时,与char[N][N]
的存储方式相比,可能最容易解释问题。
例如,假设一个char[3][3]
数组初始化如下:
char matrix[3][3];
int count = 0;
for(int i = 0; i < 3; ++i)
{
for(int j = 0; j < 3; ++j)
{
matrix[i][j] = count++;
}
}
这将在内存中列出如下:
0 1 2 3 4 5 6 7 8 9
请注意,元素在内存中按顺序排列,没有指针。
变量matrix
也可以解释为char[3]*
,它指向数组中的第一个元素。
取消引用char[3]*
会返回char[3]
数组,而该数组又可以与另一个[]
运算符取消引用。因此matrix
的元素0可以被认为是数组[0, 1, 2]
。我们可以使用另一个[]
运算符来取消引用该数组的特定元素。
另一方面,char**
在取消引用时返回char*
。访问char**
的特定元素会产生char*
。在上面的示例中,访问数组矩阵的元素0返回值0.然后将其视为char*
并使用另一个[]
运算符取消引用它将尝试访问char
在内存位置0 +一些偏移量。这几乎肯定会导致段错误。
答案 2 :(得分:0)
如果需要指向字符数组的指针,则可以创建指针并将其指向需要访问的行,如下所示。
int main()
{
char matrix[10][10];
char* array;
matrix[2][3] = 'c';
array= matrix[2];
printf("%c", array[3]);
return 0;
}