2

我是编程和学习数组中指针的新手。我现在有点困惑。看看下面的程序:指向数组的指针和指向指针的指针之间有什么区别?

#include <stdio.h> 
int fun(); 
int main() 
{ 
    int num[3][3]={23,32,478,55,0,56,25,13, 80}; 
    printf("%d\n",*(*(num+0)+1)); 
    fun(num); 
    printf("%d\n", *(*(num+0)+1)); 
    *(*(num+0)+0)=23; 
    printf("%d\n",*(*(num+0))); 
    return 0; 
} 
int fun(*p) // Compilation error 
{ 
    *(p+0)=0; 
    return 0; 
} 

这是我的老师的笔记写的程序。在main()函数中,在printf()函数中,解引用运算符被使用了两次,因为num是指向数组的指针,因此首次解除引用运算符将​​指向int,然后第二个指针指向该值。

我的问题是,当我将数组名称作为参数传递给函数fun()时,为什么使用*p;为什么不**p as num是一个指向数组的指针?

第二件事为什么*(p+0)用于更改数组的第零个元素的值;为什么不使用*(*(p+0)+0)=0中的main()函数*(*(num+0)+0)被用来改变零元素的值?

整件事对我来说非常混乱,但无论如何我必须理解它。我已经搜索了这个,并发现指针指向数组和指针指针之间有区别,但我不明白。

+0

多维数组是* flat *。清除有关如何实施的混淆。 – 2014-12-03 12:09:48

+0

你会从这个问题的答案得到答案http://stackoverflow.com/questions/14100240/2-dim-array-and-double-pointer?lq = 1 – 999k 2014-12-03 12:18:11

+0

难道你不会得到编译错误,原型/功能不匹配?为什么你问+ 0 + 0而不是+0?为什么在代码中添加静态0? – dhein 2014-12-03 12:42:35

回答

1

这个例子显示了一个矩阵,指针数组的第一个整数,指针的指针

#include<stdio.h> 
int fun(int (*p)[3]); /* p is pointer to array of 3 ints */ 
int main() 
{ 
    /* matrix */ 
    int num[3][3]={{23,32,478},{55,0,56},{25,13, 80}}; 
    /* three pointers to first integer of array */ 
    int *pnum[3] = {num[0], num[1], num[2]}; 
    /* pointer to pointer */ 
    int **ppnum = pnum; 
    printf("%d\n", *(*(num+1)+2)); 
    fun(num); 
    printf("%d\n", *(*(num+1)+2)); 
    pnum[1][2] = 2; 
    printf("%d\n", *(*(num+1)+2)); 
    ppnum[1][2] = 3; 
    printf("%d\n", *(*(num+1)+2)); 
    return 0; 
} 
int fun(int (*p)[3]) 
{ 
    p[1][2]=1; 
    return 0; 
} 
+1

我没有得到任何错误 – user4156958 2014-12-03 12:44:35

0

你实际上并不需要任何指针在这里印什么。

您的int num[3][3]实际上是一个由三个元素组成的数组,每个元素都是一个由三个整数组成的数组。因此,num[0][0] = 23,num[1][1] = 0等等。因此你可以说printf("%d", num[0][0])打印数组的第一个元素。

+0

我知道我可以做到这一点,但我想知道它与指针和我的问题是,为什么*(P + 0)用于初始化0为什么不* *(*(p + 0) +0)?因为num是指向数组的指针 – user4156958 2014-12-03 12:51:29

+0

如果您必须使用指针,那么只需使用'p'。已知'p'是函数定义中的一个指针,所以你可以说'p = 0;''''''''''''''''''''''尝试一下。 – Gophyr 2014-12-03 12:54:35

0

指针变量:

指针是变量,其存储地址(的变量)。每个人都知道。


指针数组:

数组是具有相同对象的组的开始点(地址)的变量。

而指针是一个存储数组起点(地址)的变量。

例如:

int iArray[3]; 

iArray是具有三个整数的地址值的可变和存储器是静态分配。以下语法以典型的编程语言提供。

// iArray[0] = *(iArray+0); 
// iArray[1] = *(iArray+1); 
// iArray[2] = *(iArray+2); 

在上面的iArray是一个变量,我们可以通过它使用上面提到的任何语法来访问这三个整数变量。

*(iArray + 0); //这里iArray + 0是第一个对象的地址。 * *是取消引用 *(iArray + 1); //这里iArray + 1是第二个对象的地址。 *要解除引用

这么简单,有什么可以混淆的。


以下线的理解

int iArray1[3]; 
int iArray2[3][3]; 

int *ipArray = 0; 

ipArray = iArray1;  // correct 
ipArray = iArray2[0];  // correct 
ipArray = iArray2[2];  // correct 
int **ippArray = iArray2; // wrong 

按照上面的最后一行,编译器不会把它作为一个有效的分配。所以** p没有使用。

由于分配内存的方式,指针关节不能应用于双数组。

+1

你在回答中根本没有谈到数组指针。 – newacct 2014-12-03 23:08:20

3

诀窍是阵列指针衰减:当你提到一个数组的名字时,它会在几乎所有上下文中衰变成一个指向其第一个元素的指针。那就是num只是一个由三个整数组成的阵列(类型= int [3][3])。

让我们分析表达式*(*(num + 1) + 2)

当您在表达式*(num + 1)中提到num时,它会衰减为指向其第一个元素的指针,该元素是一个由三个整数组成的数组(第一个元素为int (*)[3])。在这个指针指针算术被执行,并且指针指向的大小被添加到指针的值。在这种情况下,它是一个由三个整数组成的数组的大小(在许多机器上是12个字节)。取消引用指针后,您将剩下一个类型int [3]

但是,这种解除引用只涉及类型,因为紧接在解引用操作之后,我们看到表达式*(/*expression of type int[3]*/ + 2),所以内部表达式衰减回到指向第一个数组元素的指针。该指针包含与num + 1产生的指针相同的地址,但它具有不同的类型:int*。因此,这个指针的指针运算会将指针前进两个整数(8个字节)。因此,表达式*(*(num + 1) + 2)将产生整数元素,其偏移量为12 + 8 = 20字节,这是数组中的第六个整数。


关于你关于fun()通话问题,该呼叫实际上是打破了,只有工作,因为你的老师并没有包括在fun()向前声明的参数。代码

int fun(int* arg); 

int main() { 
    int num[3][3] = ...; 
    ... 
    fun(num); 
} 

由于错误的指针类型会产生编译时错误。由于指向num中第一个数组的指针与指向num中第一个数组的第一个元素的指针相同,因此您的教师的代码“工作”。即他的代码相当于

int fun(int* arg); 

int main() { 
    int num[3][3] = ...; 
    ... 
    //both calls are equivalent 
    fun(num[0]); 
    fun(&num[0][0]); 
} 

这将编译没有错误。

相关问题