简体   繁体   English

无法将数组转换为指针

[英]Cannot cast array to pointer

I have the following source: 我有以下来源:

#include <iostream>
using namespace std;

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

when I compile it using VS2010 I get this error: 当我使用VS2010编译它时,我收到此错误:

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

I thought arrays in c++ were just pointers. 我认为c ++中的数组只是指针。 So a char[][] could also be char** . 所以char[][]也可以是char** What am I doing wrong? 我究竟做错了什么?

Arrays aren't pointers. 数组不是指针。

An array decays to a pointer in most circumstances, but this isn't recursive. 在大多数情况下,数组会衰减到指针,但这不是递归的。 So a T[] decays to a T * , but a T[][] doesn't decay to a T** . 所以T[]衰减到T * ,但T[][]不会衰减到T**

I suggest reading the whole of the C FAQ chapter on arrays and pointers ; 我建议阅读关于数组和指针的整个C FAQ 章节 ; in particular, the section on 2D arrays and pointers-to-pointers . 特别是关于2D数组和指针指针的部分

The existing answers, though correct, don't make it very clear that there is a fundamental reason (apart from the language rules) why you cannot cast char [10][10] to char ** . 现有的答案虽然正确,但并没有明确说明为什么你不能将char [10][10]转化为char **有一个根本原因(除了语言规则)。 Even if you force the cast by saying something like 即使你强迫演员表达类似的东西

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

it won't actually work. 它实际上不会起作用。

The reason is that in C and C++ a two-dimensional array is laid out in memory as an array of arrays. 原因是在C和C ++中,二维数组在内存中布局为数组数组。 That is, in C a two-dimensional array is laid out in memory as a single allocation, 也就是说,在C中,二维数组作为单个分配布局在内存中,

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

You'll notice that arr doesn't point to a char * but to arr[0][0] which is a char ; 你会注意到arr没有指向char *但是指向arr[0][0]这是一个char ; therefore, while arr can be cast to a char * , it cannot be cast to a char ** . 因此,虽然arr可以转换为char * ,但它不能转换为char **

The correct forced cast would be 正确的强迫演员会是

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

If you don't want to force the cast (always a good idea if possible!) you would say 如果你不想强制演员(如果可能的话,总是一个好主意!)你会说

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

or, to make the outcome clearer, 或者,为了使结果更清楚,

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

And you now have (in effect) a pointer to an array of 4 characters. 而且你现在(实际上)有一个指向4个字符数组的指针。 [Proviso: I can't find anything in the C standard that prohibits an implementation from adding padding between two rows of an array, but I don't believe that any real-world implementations do so, and common coding practice depends on the assumption that there will be no such padding.] [Proviso:我在C标准中找不到任何禁止实现在数组的两行之间添加填充的内容,但我不相信任何实际的实现都这样做,并且常见的编码实践取决于假设没有这样的填充。]

If you really needed to convert arr to a char ** you would have to explicitly create an array of pointers: 如果你真的需要将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;

The C language could in principle do this for you automatically if you tried to cast a two-dimensional array to a pointer-to-pointer but that would violate the programmer's expectation that a cast does not have side-effects such as allocating memory. 如果你试图将二维数组转换为指针指针,C语言原则上可以自动执行此操作,但这会违反程序员对转换没有副作用(例如分配内存)的期望。

In Java, by way of comparison, a two-dimensional array is always an array of pointers to arrays, so that the array 在Java中,通过比较,二维数组总是一个指向数组的指针数组,因此就是数组

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

is laid out in memory as three separate allocations, in arbitrary order and not necessarily adjacent, 在内存中作为三个单独的分配,按任意顺序排列,不一定相邻,

arr -> arr[0]
       arr[1]

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

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

You will immediately notice that this requires more memory than the equivalent C array, and is slower to evaluate at runtime. 您会立即注意到这需要比等效C数组更多的内存,并且在运行时评估的速度较慢。 On the other hand, it does allow the rows of an array to have different lengths. 另一方面,它确实允许数组的行具有不同的长度。

The types char[10][10] and char** and char (*)[10] are all different types. char[10][10]char**以及char (*)[10]类型都是不同的类型。 However, the first one cannot convert into the second one, it can convert into the third one. 但是,第一个无法转换为第二个,它可以转换为第三个。

So try this: 试试这个:

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

It will work, because as I said object of type char[10][10] can convert into an object of type char (*)[10] . 它会工作,因为正如我所说的char[10][10]类型的对象可以转换为char (*)[10]类型的对象。 They're compatible types. 它们是兼​​容的类型。

I thought arrays in c++ were just pointers. 我认为c ++中的数组只是指针。

No, an array is a set of objects laid out contiguously in memory. 不,数组是在内存中连续布局的一组对象。 In some circumstances, they are convertible to a pointer to the first element. 在某些情况下,它们可以转换为指向第一个元素的指针。

So a char[][] could also be char** 所以char[][]也可以是char**

No. It is convertible to a pointer to the first one-dimensional array (which is the type char (*)[10] mentioned in the error message); 不可以。它可以转换为指向第一个一维数组的指针(它是错误消息中提到的char (*)[10]类型); but that array is not a pointer, so it is not convertible to a pointer-to-pointer. 但该数组不是指针,因此它不能转换为指向指针的指针。

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

The error exactly tells you whats wrong a double dimensional array can be assigned to an pointer to array not an double pointer. 错误确切地告诉你什么是错误的,可以将双维数组分配给指向数组的指针而不是双指针。 So what you need is: 所以你需要的是:

char (*ptr)[10] = arr; 

What am I doing wrong? 我究竟做错了什么?

First things first 首先要做的事情
Arrays are not pointers!! 数组不是指针!! but they act sometimes like pointers. 但他们有时像指针一样行事。

The rule is: 规则是:

An expression with array type (which could be an array name) converts to a pointer anytime an array type is not legal, but a pointer type is. 数组类型(可以是数组名称)的表达式只要数组类型不合法,但指针类型为,就会转换为指针。

So if you have a single dimensional array: 所以如果你有一个单维数组:

char arr[10];

Then arr decays to address of the zeroth element it has the type char * . 然后arr衰减到第0个元素的地址,它有char *类型。 Hence: 因此:

char *ptr = arr;

But if you have an 2 dimensional array which is essentially an array of arrays. 但是如果你有一个二维数组,它本质上是一个数组数组。

 char arr[10][10];

Then arr decays to the pointer to an array of 10 characters. 然后arr衰减到指向10个字符数组的指针。

So, In order to assign arr to something, you will need that something to match the type, which is pointer to an array of characters. 所以,为了给某些东西分配arr ,你需要一些东西来匹配类型,这是指向一个字符数组的指针。
Hence: 因此:

char (*ptr)[10] = arr; 

Arrays are NOT just pointers -- arrays are arrays. 数组不只是指针 - 数组是数组。 Arrays are not first-class types, however, so you can't use them in many places. 但是,数组不是一流的类型,所以你不能在很多地方使用它们。 The thing that causes your confusion is that array names CAN be implicitly converted into pointers to the array's first element, which means that you can use an array in many places where you need a pointer and it 'just works'. 引起混淆的是数组名称可以隐式转换为指向数组第一个元素的指针,这意味着您可以在需要指针的许多地方使用数组并且它“正常工作”。 This, however, is not one of those places. 然而,这不是那些地方之一。

Arrays are not pointers (I notice a lot of books tend to make you think this, though). 数组不是指针(我注意到很多书往往会让你想到这一点)。 They are something completely different. 他们是完全不同的东西。 A pointer is a memory address while an array is a contiguous set of some data. 指针是内存地址,而数组是某些数据的连续集合。

In some cases, an array can decay to a pointer to its first element. 在某些情况下,数组可以衰减为指向其第一个元素的指针。 You can then use pointer arithmetic to iterate through the contiguous memory. 然后,您可以使用指针算法迭代连续的内存。 An example of this case would be when passing an array to a function as a parameter. 这种情况的一个例子是将数组作为参数传递给函数。

What you probably want to do here is something like: 您可能想要做的是:

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

Obviously you'll need to use 2D arrays and char** in your case. 显然你需要在你的情况下使用2D数组和char **。 I'll leave that to you to figure out :) 我会留给你弄清楚:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM