从C中的指针检索2D数组

时间:2021-09-28 02:46:42

I tried the following code

我尝试了以下代码

    char arr[5] = {'A', 'E', 'I', 'O', 'U'};
    char (*p_arr)[1] = &arr;
    printf("%c\n", p_arr[0][4]); //returns 'U'

On this * thread,

在这个*线程上,

    char (*p_arr2D)[m] = &arr2D //or arr2D

is also a syntax for the decay of a n*m 2D-array arr2D, returning a pointer to its first element, an array of m elements.

也是n * m 2D阵列arr2D衰减的语法,返回指向其第一个元素的指针,m个元素的数组。

p_arr[0] seems to be the "reverse" array decay, retrieving a 2D array from a pointer to an array. How can that happen ? In the code snippet above, is p_arr interpreted as a 1*5 array (from the original 1D-array with 5 elements) ?

p_arr [0]似乎是“反向”数组衰减,从指向数组的指针中检索2D数组。怎么会发生这种情况?在上面的代码片段中,p_arr被解释为1 * 5数组(来自原始的1D数组,有5个元素)?

4 个解决方案

#1


1  

a 2D array is stored in memory like a 1D array How are multi-dimensional arrays formatted in memory?

2D数组像1D数组一样存储在内存中如何在内存中格式化多维数组?

the char (*p_arr)[1] = &arr; creates a pointer to an array of char pointers with one element ( (*p_arr)[1] ) and by the assignment &arr this pointer gets the address of an already existing array with 5 elements

char(* p_arr)[1] =&arr;创建一个指向char指针数组的指针,该指针包含一个元素((* p_arr)[1]),并通过赋值&arr这个指针获取具有5个元素的已存在数组的地址

so printf("%c\n", p_arr[0][4]); prints the 5th element ( U ) because by p_arr[0][4] adresses the 5th element in line 1

所以printf(“%c \ n”,p_arr [0] [4]);打印第5个元素(U),因为通过p_arr [0] [4]来处理第1行中的第5个元素

printf("%c\n", p_arr[1][4]); would give an error

printf(“%c \ n”,p_arr [1] [4]);会给出错误

so the reason why this code works is that a 2D array is stored in memory like a 1D array

所以这段代码的工作原理是2D数组像1D数组一样存储在内存中

#2


1  

This declaration

char (*p_arr)[1] = &arr;

is incorrect because the declared pointer and the initializer have incompatible types. There is no implicit conversion from the type char ( * )[5], the type of the initializer, to the type char ( * )[1], the ty[e of the declared pointer. So you need an explicit casting to reinterpret a pointer of one type as a pointer of another type as for example

是不正确的,因为声明的指针和初始化程序具有不兼容的类型。没有从类型char(*)[5](初始化程序的类型)到类型char(*)[1]的隐式转换,即[e]声明的指针。因此,您需要显式转换以将一种类型的指针重新解释为另一种类型的指针,例如

char (*p_arr)[1] = ( char ( * )[1] )&arr;

As for your question then if you have an object of type T where T is some type

至于你的问题,如果你有一个类型为T的对象,其中T是某种类型

T obj;

and a pointer to the object like

和指向对象的指针

T *ptr = &obj;

then expression *ptr or ptr[0] yields the referenced object of the type T.

然后表达式* ptr或ptr [0]产生类型为T的引用对象。

So let's assume that you have the following declarations

因此,我们假设您有以下声明

char arr[5] = {'A', 'E', 'I', 'O', 'U'};
char (*p_arr)[5] = &arr;

For the type char[5] that is the type of the variable arr you can introduce a typedef name.

对于char [5]类型,它是变量arr的类型,您可以引入一个typedef名称。

typedef char T[5];

Then the declarations will look like

然后声明看起来像

T arr = {'A', 'E', 'I', 'O', 'U'};
T *p_arr = &arr;

As it was mentioned above the expression *p_arr or p_arr[0] yields the referenced object of the type T that is of the type char[5].

如上所述,表达式* p_arr或p_arr [0]产生类型为T [char]类型的引用对象。

From the C Standard (6.5.3.2 Address and indirection operators)

从C标准(6.5.3.2地址和间接运算符)

4 The unary * operator denotes indirection. If the operand points to a function, the result is a function designator; if it points to an object, the result is an lvalue designating the object. If the operand has type ‘‘pointer to type’’, the result has type ‘‘type’’. If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.

4一元*运算符表示间接。如果操作数指向函数,则结果是函数指示符;如果它指向一个对象,则结果是指定该对象的左值。如果操作数具有类型''指向类型'的指针,则结果具有类型''type''。如果为指针分配了无效值,则unary *运算符的行为未定义。

And (6.5.2.1 Array subscripting)

并且(6.5.2.1数组下标)

2 A postfix expression followed by an expression in square brackets [] is a subscripted designation of an element of an array object. The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2))). Because of the conversion rules that apply to the binary + operator, if E1 is an array object (equivalently, a pointer to the initial element of an array object) and E2 is an integer, E1[E2] designates the E2-th element of E1 (counting from zero).

2后缀表达式后跟方括号[]中的表达式是数组对象元素的下标名称。下标运算符[]的定义是E1 [E2]与(*((E1)+(E2)))相同。由于适用于binary +运算符的转换规则,如果E1是数组对象(等效地,指向数组对象的初始元素的指针)并且E2是整数,则E1 [E2]指定E2的第E2个元素。 E1(从零开始计数)。

and at last (6.5.6 Additive operators)

最后(6.5.6添加剂操作员)

7 For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.

7出于这些运算符的目的,指向不是数组元素的对象的指针与指向长度为1的数组的第一个元素的指针的行为相同,其中对象的类型为其元素类型。

So in this declaration

所以在这个宣言中

char arr[5] = {'A', 'E', 'I', 'O', 'U'};
char (*p_arr)[5] = &arr;

the pointer p_arr does not point to an array element. However it can behaves as it points to the first element of an array of length 1. You can imagine it the following way

指针p_arr不指向数组元素。但是它可以表现为它指向长度为1的数组的第一个元素。您可以通过以下方式想象它

char arr[1][5] = { {'A', 'E', 'I', 'O', 'U'} };
char (*p_arr)[5] = arr;

So the expression p_arr[0] gives the first element of the imagined two-dimensional array that is an element of the type char[5].

所以表达式p_arr [0]给出了想象的二维数组的第一个元素,它是char [5]类型的元素。

#3


1  

To begin with, the line char (*p_arr)[1] = &arr; is not valid C. Your compiler must give a diagnostic message. p_arr is an array pointer to an array of 1 char, but you assign it to point at an array of 5 char.

首先,行char(* p_arr)[1] =&arr;无效C.您的编译器必须提供诊断消息。 p_arr是指向1个char的数组的数组指针,但是您将其指定为指向5个char的数组。

As for why it seems like you have a 2D array - you don't have one - is because p_arr[0] works like any other pointer arithmetic, giving you pointed-at item "offset + 0". Which is the array. And then you access item 4 in the array.

至于为什么看起来你有一个2D数组 - 你没有一个 - 是因为p_arr [0]的工作方式与任何其他指针算法一样,给你指向的项目“offset + 0”。哪个是阵列。然后您访问数组中的第4项。

A simple example of the very same pointer arithmetic principle would be this:

一个简单的指针算术原理示例如下:

int a;
int* ptr = &a;
ptr[0] = whatever; // perfectly valid C

ptr[0] is guaranteed to be equivalent to *(ptr+0).

ptr [0]保证等于*(ptr + 0)。

Correct use of the array pointer should be printf("%c\n", (*p_arr)[4]). In this case it happened to work, but in other cases you might invoke undefined behavior, since p_arr is not allowed to point beyond the allocated memory.

正确使用数组指针应该是printf(“%c \ n”,(* p_arr)[4])。在这种情况下,它恰好工作,但在其他情况下,您可能会调用未定义的行为,因为不允许p_arr指向超出分配的内存。

#4


0  

You are declaring p_arr to be a pointer to an array of chars (and that array is of length one which is a sure sign of a problem).

您声明p_arr是一个指向字符数组的指针(该数组长度为1,这是一个问题的确定标志)。

You may want the much simpler syntax:

您可能需要更简单的语法:

char *p_arr = arr;

or maybe:

#include <stdio.h>

int main() {
    char arr[] = {"Hello world"};
    char *p[3] = {NULL, arr, NULL};

    printf("%s %c\n", p[1], p[1][3]);
}

John

#1


1  

a 2D array is stored in memory like a 1D array How are multi-dimensional arrays formatted in memory?

2D数组像1D数组一样存储在内存中如何在内存中格式化多维数组?

the char (*p_arr)[1] = &arr; creates a pointer to an array of char pointers with one element ( (*p_arr)[1] ) and by the assignment &arr this pointer gets the address of an already existing array with 5 elements

char(* p_arr)[1] =&arr;创建一个指向char指针数组的指针,该指针包含一个元素((* p_arr)[1]),并通过赋值&arr这个指针获取具有5个元素的已存在数组的地址

so printf("%c\n", p_arr[0][4]); prints the 5th element ( U ) because by p_arr[0][4] adresses the 5th element in line 1

所以printf(“%c \ n”,p_arr [0] [4]);打印第5个元素(U),因为通过p_arr [0] [4]来处理第1行中的第5个元素

printf("%c\n", p_arr[1][4]); would give an error

printf(“%c \ n”,p_arr [1] [4]);会给出错误

so the reason why this code works is that a 2D array is stored in memory like a 1D array

所以这段代码的工作原理是2D数组像1D数组一样存储在内存中

#2


1  

This declaration

char (*p_arr)[1] = &arr;

is incorrect because the declared pointer and the initializer have incompatible types. There is no implicit conversion from the type char ( * )[5], the type of the initializer, to the type char ( * )[1], the ty[e of the declared pointer. So you need an explicit casting to reinterpret a pointer of one type as a pointer of another type as for example

是不正确的,因为声明的指针和初始化程序具有不兼容的类型。没有从类型char(*)[5](初始化程序的类型)到类型char(*)[1]的隐式转换,即[e]声明的指针。因此,您需要显式转换以将一种类型的指针重新解释为另一种类型的指针,例如

char (*p_arr)[1] = ( char ( * )[1] )&arr;

As for your question then if you have an object of type T where T is some type

至于你的问题,如果你有一个类型为T的对象,其中T是某种类型

T obj;

and a pointer to the object like

和指向对象的指针

T *ptr = &obj;

then expression *ptr or ptr[0] yields the referenced object of the type T.

然后表达式* ptr或ptr [0]产生类型为T的引用对象。

So let's assume that you have the following declarations

因此,我们假设您有以下声明

char arr[5] = {'A', 'E', 'I', 'O', 'U'};
char (*p_arr)[5] = &arr;

For the type char[5] that is the type of the variable arr you can introduce a typedef name.

对于char [5]类型,它是变量arr的类型,您可以引入一个typedef名称。

typedef char T[5];

Then the declarations will look like

然后声明看起来像

T arr = {'A', 'E', 'I', 'O', 'U'};
T *p_arr = &arr;

As it was mentioned above the expression *p_arr or p_arr[0] yields the referenced object of the type T that is of the type char[5].

如上所述,表达式* p_arr或p_arr [0]产生类型为T [char]类型的引用对象。

From the C Standard (6.5.3.2 Address and indirection operators)

从C标准(6.5.3.2地址和间接运算符)

4 The unary * operator denotes indirection. If the operand points to a function, the result is a function designator; if it points to an object, the result is an lvalue designating the object. If the operand has type ‘‘pointer to type’’, the result has type ‘‘type’’. If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.

4一元*运算符表示间接。如果操作数指向函数,则结果是函数指示符;如果它指向一个对象,则结果是指定该对象的左值。如果操作数具有类型''指向类型'的指针,则结果具有类型''type''。如果为指针分配了无效值,则unary *运算符的行为未定义。

And (6.5.2.1 Array subscripting)

并且(6.5.2.1数组下标)

2 A postfix expression followed by an expression in square brackets [] is a subscripted designation of an element of an array object. The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2))). Because of the conversion rules that apply to the binary + operator, if E1 is an array object (equivalently, a pointer to the initial element of an array object) and E2 is an integer, E1[E2] designates the E2-th element of E1 (counting from zero).

2后缀表达式后跟方括号[]中的表达式是数组对象元素的下标名称。下标运算符[]的定义是E1 [E2]与(*((E1)+(E2)))相同。由于适用于binary +运算符的转换规则,如果E1是数组对象(等效地,指向数组对象的初始元素的指针)并且E2是整数,则E1 [E2]指定E2的第E2个元素。 E1(从零开始计数)。

and at last (6.5.6 Additive operators)

最后(6.5.6添加剂操作员)

7 For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.

7出于这些运算符的目的,指向不是数组元素的对象的指针与指向长度为1的数组的第一个元素的指针的行为相同,其中对象的类型为其元素类型。

So in this declaration

所以在这个宣言中

char arr[5] = {'A', 'E', 'I', 'O', 'U'};
char (*p_arr)[5] = &arr;

the pointer p_arr does not point to an array element. However it can behaves as it points to the first element of an array of length 1. You can imagine it the following way

指针p_arr不指向数组元素。但是它可以表现为它指向长度为1的数组的第一个元素。您可以通过以下方式想象它

char arr[1][5] = { {'A', 'E', 'I', 'O', 'U'} };
char (*p_arr)[5] = arr;

So the expression p_arr[0] gives the first element of the imagined two-dimensional array that is an element of the type char[5].

所以表达式p_arr [0]给出了想象的二维数组的第一个元素,它是char [5]类型的元素。

#3


1  

To begin with, the line char (*p_arr)[1] = &arr; is not valid C. Your compiler must give a diagnostic message. p_arr is an array pointer to an array of 1 char, but you assign it to point at an array of 5 char.

首先,行char(* p_arr)[1] =&arr;无效C.您的编译器必须提供诊断消息。 p_arr是指向1个char的数组的数组指针,但是您将其指定为指向5个char的数组。

As for why it seems like you have a 2D array - you don't have one - is because p_arr[0] works like any other pointer arithmetic, giving you pointed-at item "offset + 0". Which is the array. And then you access item 4 in the array.

至于为什么看起来你有一个2D数组 - 你没有一个 - 是因为p_arr [0]的工作方式与任何其他指针算法一样,给你指向的项目“offset + 0”。哪个是阵列。然后您访问数组中的第4项。

A simple example of the very same pointer arithmetic principle would be this:

一个简单的指针算术原理示例如下:

int a;
int* ptr = &a;
ptr[0] = whatever; // perfectly valid C

ptr[0] is guaranteed to be equivalent to *(ptr+0).

ptr [0]保证等于*(ptr + 0)。

Correct use of the array pointer should be printf("%c\n", (*p_arr)[4]). In this case it happened to work, but in other cases you might invoke undefined behavior, since p_arr is not allowed to point beyond the allocated memory.

正确使用数组指针应该是printf(“%c \ n”,(* p_arr)[4])。在这种情况下,它恰好工作,但在其他情况下,您可能会调用未定义的行为,因为不允许p_arr指向超出分配的内存。

#4


0  

You are declaring p_arr to be a pointer to an array of chars (and that array is of length one which is a sure sign of a problem).

您声明p_arr是一个指向字符数组的指针(该数组长度为1,这是一个问题的确定标志)。

You may want the much simpler syntax:

您可能需要更简单的语法:

char *p_arr = arr;

or maybe:

#include <stdio.h>

int main() {
    char arr[] = {"Hello world"};
    char *p[3] = {NULL, arr, NULL};

    printf("%s %c\n", p[1], p[1][3]);
}

John