无法将数组转换为指针

时间:2011-12-12 17:10:31

标签: c++ arrays pointers casting

我有以下来源:

#include <iostream>
using namespace std;

void main(int j)
{
    char arr[10][10];
    char** ptr;
    ptr = arr;
}

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

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

我认为c ++中的数组只是指针。因此,char[][]也可以是char**。我做错了什么?

8 个答案:

答案 0 :(得分:12)

数组不是指针。

在大多数情况下,数组会衰减到指针,但这不是递归的。因此,T[]会衰减为T *,但T[][]不会衰减为T**

我建议阅读整篇C FAQ chapter on arrays and pointers;特别是关于2D arrays and pointers-to-pointers的部分。

答案 1 :(得分:7)

现有答案虽然正确,但并未明确说明为什么你不能将char [10][10]强制转换为char **,这是一个根本原因(除语言规则外)。即使你通过说

之类的东西强迫演员
char arr[2][2];
char ** ptr = (char **)arr;

它实际上不起作用。

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

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

您会注意到arr并未指向char *,而是指向arr[0][0] char;因此,虽然可以将arr强制转换为char *,但无法将其转换为char **

正确的强制演员阵容

char arr[2][2];
char * ptr = (char *)arr;

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

char arr[2][2];
char * ptr = arr[0];

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

char arr[2][2];
char * ptr = &arr[0][0];

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

如果您确实需要将arr转换为char **,则必须显式创建指针数组:

char arr[2][2]
char * arr_ptrs[2];
char ** ptr;
arr_ptrs[0] = arr[0];
arr_ptrs[1] = arr[1];
ptr = arr_ptrs;

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

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

char arr[][] = { {'a', 'b'}, {'c', 'd'} };

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

arr -> arr[0]
       arr[1]

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

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

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

答案 2 :(得分:4)

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

所以试试这个:

char arr[10][10];
char (*ptr)[10];
ptr = arr; //ok

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

答案 3 :(得分:1)

  

我认为c ++中的数组只是指针。

不,数组是在内存中连续布局的一组对象。在某些情况下,它们可以转换为指向第一个元素的指针。

  

所以char[][]也可能是char**

没有。它可以转换为指向第一个一维数组的指针(它是错误消息中提到的类型char (*)[10]);但该数组不是指针,因此它不能转换为指针指针。

答案 4 :(得分:0)

错误确切地告诉你什么是错误的,可以将双维数组分配给指向数组的指针而不是双指针。所以你需要的是:

char (*ptr)[10] = arr; 
  

我做错了什么?

首先要做的事情 数组不是指针!! 但它们有时像指针一样。

规则是:

具有数组类型(可以是数组名称)的表达式只要数组类型不合法,但指针类型为。

,就会转换为指针。

所以如果你有一个单维数组:

char arr[10];

然后arr衰减到具有类型char *的第0个元素的地址。 因此:

char *ptr = arr;

但是如果你有一个二维数组,它本质上是一个数组数组。

 char arr[10][10];

然后arr衰减到指向10个字符数组的指针。

所以,为了将arr分配给某个东西,你需要一些东西来匹配类型,它是指向一个字符数组的指针。
因此:

char (*ptr)[10] = arr; 

答案 5 :(得分:0)

数组不只是指针 - 数组是数组。但是,数组不是一流的类型,所以你不能在很多地方使用它们。引起混淆的是数组名称可以隐式转换为指向数组第一个元素的指针,这意味着您可以在需要指针的许多地方使用数组并且它“正常工作”。然而,这不是那些地方之一。

答案 6 :(得分:0)

数组不是指针(我注意到很多书往往会让你想到这一点)。他们是完全不同的东西。指针是一个内存地址,而一个数组是一些连续的数据集。

在某些情况下,数组可以衰减为指向其第一个元素的指针。然后,您可以使用指针算法迭代连续的内存。这种情况的一个例子是将数组作为参数传递给函数。

你可能想要做的是:

char arr[10];
char * i = &arr[0];

显然你需要在你的情况下使用2D数组和char **。我会留给你弄清楚:)

答案 7 :(得分:0)

当您将ar [10] [10]转换为指针时,您将获得一个指针数组,如上所述* ar [10]而不是** ar。