整个数组的指针

问题描述 投票:0回答:3
    int main(){
        int a[][3]={1,2,3,4,5,6};
        int (*ptr)[3]=a;
        printf(" %d",(*ptr)[1]) ;
    }

我知道变量

ptr
是类型
int
的第一个1d数组的指针,换句话说变量
ptr
将存储前3个整数的地址,首先让我们假设基地址
a
1000
所以我认为这个二维数组将以这种形式存储在内存中:

elements:                  |    1     |    2     |    3     ||    4     |    5     |    6     |
addressed of each element: |   1000   | 1004     | 1008     ||   1012   | 1016     | 1020     |
                           ---------------------------------||---------------------------------
addressed of each array:                1000                              1012

所以

ptr
将存储值
1000
,这是第一个数组的地址。这意味着
*ptr
(*ptr)[0]
会给我第一个元素的地址,而
*ptr+1
((*ptr)[1])
会给我第二个元素的地址,依此类推。

据我所知

*ptr[1]
会给出第二个元素的地址,而不是它的值。

但是从输出看来我错了。所以我想知道我的过程中有什么问题。

arrays c pointers memory
3个回答
2
投票

这部分之前你是对的:

这意味着

*ptr
(*ptr)[0]
会给我第一个元素的地址

*ptr
会那样做。
(*ptr)[0]
将取消引用数组指针,然后取消引用结果数组,为您提供第一项的值,
1
.

类似地,

(*ptr)[1])
将首先给你一个数组,然后是该数组中的第二个项目,
2
.

据我所知,*ptr[1] 将给出第二个元素的地址,而不是它的值。

不,因为

[]
的优先级高于
*
,所以
ptr[1]
将首先给你第二个数组的(地址)。然后你取消引用它,你会得到第二个数组中第一项的值,
4
.

这里的关键是一旦你取消引用一个指向数组的指针,你最终会得到一个数组 - 就像任何数组在“数组衰减”等方面的行为一样


最佳实践:

  • 如果可以避免,不要使用
    *
    取消引用数组指针。
    ptr[0][0]
    不那么模糊了。这种语法是在这种情况下使用数组指针的全部要点。
  • 避免草率的初始化列表,如
    int a[][3]={1,2,3,4,5,6};
    。 C 允许它,但它是糟糕的风格并且使诊断的某些可能性静音。相反,这应该是
    int a[][3]={ {1,2,3}, {4,5,6} };
    作为奖励也是可读的,自我记录的代码。

0
投票

让我们考虑一下调用中使用的表达式

printf

printf(" %d",(*ptr)[1]) ;

对于初学者来说,指针

ptr
指向二维数组
int[3]
类型的第一个元素。

int (*ptr)[3]=a;

这是由于初始化列表

int a[][3]={1,2,3,4,5,6};

二维数组有两个

int[3]
.

类型的元素

所以取消引用指针

*ptr
你得到一个
int[3]
类型的左值,它是一个一维数组。然后对该数组应用下标运算符
( *ptr )[1]
,它产生一维数组的第二个元素。

所以值

2
将被输出。

这意味着 *ptr 或 (*ptr)[0] 会给我第一个地址 元素

表达式

*ptr
( *ptr )[0]
是两个不同类型的实体。
The expression
*ptr
yields lvalue of the type
int[3]`,使用din表达式它又可以隐式转换为指向第一个元素的指针获得的数组。

表达式

( *ptr )[0]
产生所获得的
int
类型数组的第一个标量元素。

据我所知,*ptr[1] 将给出第二个地址 元素,而不是它的价值。

表达式

ptr[1]
产生二维数组
int[3]
类型的第二个元素在这个表达式
*ptr[1]
中获得的类型
int[3]
的对象被隐式转换为类型
int *
的指针并取消引用指针产生二维数组第二个元素
int
类型的第一个元素。

为了更清楚地考虑如何评估下标运算符。

例如,表达式

ptr[0]
等同于
*( ptr + 0 )
又等同于
*ptr
.

表达式

(*ptr)[1]
等同于
ptr[0][1]
.

表达式

*ptr[1]
等同于
*(ptr[1] )
又等同于
ptr[1][0]
.

一般来说,

ptr[i][j]
可以用多种方式重写。例如

( *( ptr + i ) )[j]
*( *( ptr + i ) + j )
*( ptr[i] + j )

0
投票

首先,启用编译器警告是个好主意。然后您将被告知初始化程序中缺少大括号。这是你的程序的一个稍微清理过的版本:

#include <stdio.h>

int main(void)
{
    int a[][3] = {{1, 2, 3}, {4, 5, 6}};
    int (*ptr)[3] = a;
    printf("%d\n", (*ptr)[1]);
    return 0;
}

如果你运行它,你将得到输出“2”。这是因为

*ptr
是数组
a
的第一个元素,它本身也是一个数组,因此
(*ptr)[1]
是这个包含的数组中的第二个元素,即 2.

© www.soinside.com 2019 - 2024. All rights reserved.