C语言中数组与指针、数组指针和函数指针

来源:互联网 发布:卸载linux自带jdk 编辑:程序博客网 时间:2024/06/04 23:24

数组与指针:

先看下面一段代码:

#include <stdio.h>int main(){    int a[5]={5,4,3,2,1};    printf("%x\n", a);    printf("%x\n", a+1);    printf("%d\n", *a);    printf("%x\n", &a);    printf("%d\n", sizeof(a));    printf("%d\n", sizeof(&a));    printf("%x\n", &a+1);    return 0;}

输出结果:

22cc80
22cc84
5
22cc80
20
4
22cc94

我们知道,数组名的值是一个指针常量,它的值为数组第1个元素的地址,并不表示整个数组,所以int a[5]; int *p = a 这两条语句就很容易理解了。二维和多维数组的数组名也是同样的意义,n维数组可以看做1维数组,该数组的元素是n-1维数组。例如,二维数组int matrix[3][3],可以看做一个1维数组,包含3个元素,每个元素是一个包含3个整型元素的数组,数组名matrix是一个指向它第1个元素的指针,所以matrix是一个指向包含3个整型元素的数组的数组指针,关于数组指针下面将会讨论。上面代码的第1条输出语句输出的是a[0]的地址,第2条语句为a[1]的地址,第3条语句为a[0]的值。

但是,数组名在做为取地址操作符&sizeof的操作数时,并不是指向数组第1个元素的指针常量。&操作返回的是一个数组指针,sizeof返回整个数组的长度。第4条输出语句输出数组指针的值,注意,它和数组第一个元素的地址值是一样的,第5条语句输出数组的长度。第6条语句表明&a返回一个指针,第7条语句的输出和第4条语句的地址差值为20,刚好是数组是a的长度,证明&a返回的是数组指针。

数组指针:

int *p[ ]:[ ]运算符的优先级高于*,所以p先和[ ]结合,表示数组,数组中的元素的类型为int *,表示指向int类型的指针。该声明表示指针数组。

int (*p)[ ]:*先和p结合,意味着p是指针,p指向的元素的数据类型为int [ ]。该声明表示数组指针。

指针数组比较好理解,下面的代码主要分析数组指针。

#include <stdio.h>int main(){    int matrix[3][3]={{3,3,3},{2,2,2},{1,1,1}};    int (*p)[3] = matrix;    printf("%x\n", matrix);    printf("%x\n", matrix+1);    printf("%x\n", p);    printf("%d\n", sizeof(p));    printf("%x\n", *p);    printf("%d\n", sizeof(*p));    printf("%x\n", **p);    printf("%x\n", *p+1);    printf("%d\n", sizeof(*p+1));    printf("%x\n", *(*p+1));    return 0;}

输出结果:

22cc70
22cc7c
22cc70
4
22cc70
12
3
22cc74
4
3

int (*p)[3]定义了数组指针,matrix是一个指向包含3个整型元素的数组的数组指针,第1、2条输出语句表明数组名matrix的意义,第3、4条语句说明p是一个指针,它的值和matrix相等。随后6条输出语句表明,数组指针解引用得到的是一个数组,类似于数组名,它的类型是指向数组中元素的指针。

函数指针:

看下面一段代码:

#include <stdio.h>int func(int m){    printf("%d\n", m);    return 0;}int main(){    int (*pf)(int);    pf = func;    pf(0);    (*pf)(1);    pf = &func;    pf(2);    (*pf)(3);    pf = *func;    pf(4);    (*pf)(5);    (&func)(6);    (*func)(7);    (******pf)(8);    printf("%x\n", func);    printf("%x\n", pf);    printf("%x\n", &func);    printf("%x\n", &pf);    printf("%x\n", *func);    printf("%x\n", *pf);    printf("%x\n", ******func);    printf("%x\n", ******pf);    return 0;}

输出结果:

0
1
2
3
4
5
6
7
8
401050
401050
401050
22cca4
401050
401050
401050
401050

函数名是函数的入口地址,函数名被使用时总是由编译器把它转换为函数指针。所以语句pf=func和pf=&func是等价的,后一种赋值方式把编译的工作显示的执行了,对于语句pf=*func,编译器首先将func转换为函数指针,然后解引用,相当于把函数指针又转换为函数名,所以编译器还要再一次将其转换为函数指针。其他输出语句的&运算和*运算都可以按上述方法来理解。

参考:

1、C程序设计语言(K&R),中文版第二版

2、C和指针

3、酷壳--深入理解C语言

4、酷壳--谁说C语言很简单?