无法将数组转换为指针

ato*_*erz 7 c++ arrays pointers casting

我有以下来源:

#include <iostream>
using namespace std;

void main(int j)
{
    char arr[10][10];
    char** ptr;
    ptr = arr;
}
Run Code Online (Sandbox Code Playgroud)

当我使用VS2010编译它时,我收到此错误:

error : a value of type "char (*)[10]" cannot be assigned to an entity of type "char **"
Run Code Online (Sandbox Code Playgroud)

我认为c ++中的数组只是指针.所以char[][]也可以char**.我究竟做错了什么?

Oli*_*rth 12

数组不是指针.

在大多数情况下,数组会衰减到指针,但这不是递归的.所以一个T[]衰变到一个T *,但一个T[][]不衰败到一个T**.

我建议阅读关于数组和指针的整个C FAQ 章节 ; 特别是关于2D数组和指针指针的部分.


Har*_*ton 7

现有的答案,虽然是正确的,不让它很清楚,有一个根本的原因(除了语言规则),为什么你不能投char [10][10]char **.即使你强迫演员表达类似的东西

char arr[2][2];
char ** ptr = (char **)arr;
Run Code Online (Sandbox Code Playgroud)

它实际上不会起作用.

原因是在C和C++中,二维数组在内存中布局为数组数组.也就是说,在C中,二维数组作为单个分配布局在内存中,

arr -> arr[0][0]
       arr[0][1]
       arr[1][0]
       arr[1][1]
Run Code Online (Sandbox Code Playgroud)

你会注意到arr它并不是指向a char *而是指向arr[0][0]a char; 因此,虽然arr可以投射到a char *,但它不能被投射到char **.

正确的强迫演员会是

char arr[2][2];
char * ptr = (char *)arr;
Run Code Online (Sandbox Code Playgroud)

如果你不想强制演员(如果可能的话,总是一个好主意!)你会说

char arr[2][2];
char * ptr = arr[0];
Run Code Online (Sandbox Code Playgroud)

或者,为了使结果更清楚,

char arr[2][2];
char * ptr = &arr[0][0];
Run Code Online (Sandbox Code Playgroud)

而且你现在(实际上)有一个指向4个字符数组的指针.[Proviso:我在C标准中找不到任何禁止实现在数组的两行之间添加填充的内容,但我不相信任何实际的实现都这样做,并且常见的编码实践取决于假设没有这样的填充.]

如果你真的需要转换arr为a,char **你必须显式创建一个指针数组:

char arr[2][2]
char * arr_ptrs[2];
char ** ptr;
arr_ptrs[0] = arr[0];
arr_ptrs[1] = arr[1];
ptr = arr_ptrs;
Run Code Online (Sandbox Code Playgroud)

如果你试图将二维数组转换为指针指针,C语言原则上可以自动执行此操作,但这会违反程序员对转换没有副作用(例如分配内存)的期望.

在Java中,通过比较,二维数组总是一个指向数组的指针数组,因此就是数组

char arr[][] = { {'a', 'b'}, {'c', 'd'} };
Run Code Online (Sandbox Code Playgroud)

在内存中作为三个单独的分配,按任意顺序排列,不一定相邻,

arr -> arr[0]
       arr[1]

arr[0] -> arr[0][0]
          arr[0][1]

arr[1] -> arr[1][0]
          arr[1][1]
Run Code Online (Sandbox Code Playgroud)

您会立即注意到这需要比等效C数组更多的内存,并且在运行时评估的速度较慢.另一方面,它确实允许数组的行具有不同的长度.


Naw*_*waz 6

类型char[10][10]char**char (*)[10]都是不同的类型。但是,第一个不能转换为第二个,它可以转换为第三个。

所以试试这个:

char arr[10][10];
char (*ptr)[10];
ptr = arr; //ok
Run Code Online (Sandbox Code Playgroud)

它会起作用,因为正如我所说的 object of typechar[10][10]可以转换为 type 的对象char (*)[10]。它们是兼​​容的类型。