我有以下来源:
#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**
。我做错了什么?
答案 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。