数组指针,指针数组和函数指针
来源:互联网 发布:计算微积分的软件 编辑:程序博客网 时间:2024/04/30 06:47
数组指针:首先呢他是一个指针,他有能力指向一个数组。
指针:其数值为地址的变量。
int (*p)[3]; // p首先与*结合,所以他呢是一个指针,他可以指向一个数组,这个数组有三个元素,每个元素为整形。
指针数组:首先呢他是一个数组,他的每一个元素为一个指针。
数组:由一系列类型相同的元素构成。
int *p[3]; // []的优先级高于 *,所以p首先是一个数组,这个数组有三个元素,每个元素为一个指针。
可以看出 p与谁先结合决定了他的类型是什么。
[] 的优先级高于*;() 的优先级高于[];
详解:
(1):数组在内存中的表示
创建一个数组,就是在内存中开辟了一块连续的空间。
二维数组是特殊的一位数组。
int main() { int a[2][2]={1,2,3,4};//这是一个2*2的二维数组 int (*p)[2];//数组指针 p=a;//令p指向数组a return 0; }
int (p)[2];p首先与‘’ 结合,所以p是一个指针,他可以指向一个数组,这个数组有两个元素。
(2)理解数组名和数组指针变量
a是一个数组名,类型是指向一维数组的指针,不是变量,a的值是指针常量,即不能有a++或者a=p这些操作。a指向这块连续空间的首地址,值是&a[0][0]。
a[0]是一维数组名,类型是指向整型的指针,值是&a[0][0],这个值是一个常量。
a[1]是一维数组名,类型是指向整型的指针,值是&a[1][0],这个值是一个常量。
p是一个数组指针变量,指向一维数组的指针变量,值是&a[0][0]。可以执行p++;p=a等操作。
a+1是取出第一行的首地址。
*(a+1)表示指向下一行元素,也可以理解为指向下一个一维数组。
a[0]+1是指向第0行第1个元素,也可以理解为指向一维数组a[0]的第一个元素。
p+1同a+1
(p+1)同(a+1)
虽然a跟a[0]值是一样,但类型不一样,表示的意义不一样。通过分析就不难理解为什么((a+i)+j)和a[i][j]等效了。
#include <stdio.h> int main(){ int a[2][2] = { 1, 2, 3, 4 }; int(*p)[2]; p = a; printf("a = %p, p = %p, &a[0][0] = %p\n", a, p, &a[0][0]); system("pause"); return 0;}
输出结果一致,数值均为数组首元素地址。
(3)利用指针便利数组
#include<stdio.h> #define M 2 #define N 3 int main(){ int a[M][N] = { 1, 2, 3, 4, 5, 6 }; int *start = &a[0][0]; int * const end = start + M*N; for (; start != end; start++) printf("%-5d", *start); putchar('\n'); system("pause"); return 0;}
输出结果
1 2 3 4 5 6
用指针遍历一个二维数组,同时也可以说明二维数组其实就是连续的一维数组。
(4)数组名与数组指针变量的区别
从(2)中的分析中得出数组名是指针,类型是指向元素类型的指针,但值是指针常量,声明数组时编译器会为声明所指定的元素数量保留内存空间。
数组指针是指向数组的指针,声明指针变量时编译器只为指针本身保留内存空间。
#include<stdio.h> int main(){ int a[2][2] = { 1, 2, 3, 4 }; int(*p)[2];//数组指针 p = a;//令p指向数组a printf("%d\n%d\n", sizeof(a), sizeof p); system("pause"); return 0;}
输出结果:
16
4
sizeof() :关键字,并非函数,其作用为返回一个对象或者类型所占的内存字节数。
有输出结果可以看出**size(数组名)代表整个数组**4个int
指针p为一个地址。
#include<stdio.h> void main() { int a[2][2]={1,2,3,4}; int (*p)[2]; p=a; printf("%d\n%d\n",sizeof(a+1),sizeof(p+1)); printf("%d\n%d\n",sizeof(a+0),sizeof(p+0)); printf("%p\n%p\n", a + 1, p + 1); printf("%p\n%p\n", a + 0, p + 0); }
输出结果
可见,a+i 变成为一个指针常量,
a+1 与 p+1 取到的地址也是相同的。
#include<stdio.h> void f(int a[][2]){ printf("%d\n", sizeof a);}int main(){ int a[2][2] = { 1, 2, 3, 4 }; printf("%d\n", sizeof a); f(a); system("pause"); return 0;}
输出结果
16
4
传参的时候数组名转化成指针变量,注意到函数f中f(int a[][2])这里并不需要指定二维数组的长度,此处可以改为int (*a)[2]。所以传过来的就是一个数组指针变量。
总结:数组名单独出现在sizeof内部时代表整个数组,具体看以前博客。(a+1)的类型是一个指针变量。把数组名作为参数传递的时候实际上传递的是一个指针变量。sizeof对变量和数组名操作时返回的结果会不一样。数组指针是指向数组的指针,其值可以是变量。
指针数组
(1)指针数组简单认识
指针数组:存放指针的数组
#include<stdio.h> int main(){ int i = 1, j = 2; //p先跟[]结合,然后再跟*结合 int *p[2];//指针数组,存放指针的数组 p[0] = &i; p[1] = &j; printf("%d", sizeof(p)); system("pause"); return 0;}
输出结果
8
首先呢p为一个数组,有两个元素,每个元素为一个整形指针。2*4
(2)多维数组与多级指针
A:二维数组
#include <stdio.h> int main (void) { int a[3][2] = {{0, 1}, {2, 3}, {4, 5}}; int *p; p = a[0]; printf ("%d\n", p[0]); system("pause"); return 0; }
输出结果
0
#include <stdio.h> int main(void){ int a[3][2] = { (0, 1), (2, 3), (4, 5) }; int *p; p = a[0]; printf("%d\n", p[0]); system("pause"); return 0;}
输出结果
1
分析上述代码初始化部分
int a[3][2] = {{0, 1}, {2, 3}, {4, 5}};
int a[3][2] = {(0, 1), (2, 3), (4, 5) };
第一个为常见的初始赋值;
第二个则是一个逗号表达式,等价于 int a [3][2]={ 1, 3, 5};不完全的初始化赋值。
考虑存储大小:
#include <stdio.h> int main (void) { int a[3][2] = {0, 1, 2, 3, 4, 5}; int *p; p = a[0]; printf ("%d\n", p[0]); printf ("sizeof (a) = %d, sizeof (a[1]) = %d, sizeof (a[2][1]) = %d\n", sizeof (a), sizeof (a[1]), sizeof (a[2][1])); return 0; }
输出结果:
0
sizeof (a) = 24, sizeof (a[1]) = 8, sizeof (a[2][1]) = 4
B:二级指针
#include <stdio.h> int main(void){ char *p = "abcdef"; char **p1 = &p; system("pause"); return 0;}
二级指针即存放地址的指针。
(3)函数指针
显而易见,函数指针为指向函数的指针。
分析下面的函数指针:
char * (fun)(char p1,char * p2);
fun首先与 ‘*’结合所以呢他是一个指针,去掉(*fun)
char * (char * p1,char * p2);
可见fun这个指针变量指向了一个函数,这个函数的参数 (char * p1,char * p2);返回类型为 char*。
相当于char * ()(char p1,char * p2) fun1;
char *my_strcpy(char *dest, const char *src){ char *tmp = dest; while ((*dest++ = *src++) != '\0') /* nothing */; return tmp;}int main(void){ char *orig = "best"; char copy[40] = "Be the best that you can be."; char *ps; ps = my_strcpy(copy + 7, orig); puts(copy); puts(ps); system("pause"); return 0;}
输出结果:
Be the best
best
了解:(int)&p 这是什么?
#include <stdio.h> void Function(){ printf("Call Function!\n");}int main(void){ void(*p)(); *(int*)&p = (int)Function; (*p) (); system("pause"); return 0;}
输出结果
Call Function!
void (*p)();
这行代码定义了一个指针变量 p, p 指向一个函数,这个函数的参数和返回值都是 void。
&p 是求指针变量 p 本身的地址。
(int*)&p 表示将地址强制转换成指向 int 类型数据的指针。
(int)Function 表示将函数的入口地址强制转换成 int 类型的数据。
(int)&p=(int)Function;表示将函数的入口地址赋值给指针变量 p。
那么(*p) ();就是表示对函数的调用。
使用函数指针的好处在于,可以将实现同一功能的多个模块统一起来标识,这样一来更容易后期的维护,系统结构更加清晰。或者归纳为:便于分层设计、利于系统抽象、降低耦合度以及使接口与实现分开。
函数指针数组
#include <stdio.h> #include <string.h> char * fun1(char * p){ printf("%s\n", p); return p;}char * fun2(char * p){ printf("%s\n", p); return p;}char * fun3(char * p){ printf("%s\n", p); return p;}int main(void){ char * (*pf[3])(char * p); //pf首先与[]结合表明pf为一个数组,这个数组有三个元素,去掉pf[] char * (*)(char * p);可以看出每个元素是一个函数指针,这个函数参数为 char* 返回类型为 char* pf[0] = fun1; pf[1] = &fun2; // 可以用函数名加上取地址符 pf[2] = fun3; pf[0]("fun1"); pf[0]("fun2"); pf[0]("fun3"); system("pause"); return 0;}
输出结果
fun1
fun2
函数指针数组的指针
#include <stdio.h> #include <string.h> char * fun1(char * p){ printf("%s\n", p); return p;}char * fun2(char * p){ printf("%s\n", p); return p;}char * fun3(char * p){ printf("%s\n", p); return p;}int main(void){ char * (*a[3])(char * p); char * (*(*pf)[3])(char * p);//pf首先与'*'结合,所以他是一个指针,去掉*pf, char * (*[3])(char * p);可以看出这个指针指向一个数组,这个数组有3个元素,去掉[3],char * (*)(char * p);可以看出每个元素为一个函数指针,参数与返回类型都为char* pf = &a; a[0] = fun1; a[1] = &fun2; a[2] = &fun3; pf[0][0]("fun1"); pf[0][1]("fun2"); pf[0][2]("fun3"); system("pause"); return 0;}
输出结果
fun1
fun2
fun3
以上就是我对数组指针,指针数组,函数指针的一些简单认识,有不足之处希望大家指出。
- 函数指针,指针数组和数组指针
- 数组指针,指针数组和函数指针
- 函数指针和指针函数 数组指针和指针数组
- 数组指针和指针数组,函数指针和指针函数
- 指针函数和函数指针、指针数组和数组指针
- 指针函数和函数指针、指针数组和数组指针
- 数组指针和指针数组 指针函数和函数指针
- 数组指针、 指针数组、函数指针、函数指针数组和指向函数指针数组的指针
- 简述指针数组 数组指针 函数指针 函数指针数组和函数指针数组的指针
- 数组指针和函数指针
- 指针函数、数组指针、函数指针、函数指针数组和指向函数指针数组的指针
- 指针,指针数组,数组指针,函数指针
- 函数指针 和 函数指针数组 和 函数指针数组
- 指针常量和常量指针、函数指针和指针函数、指针数组和数组指针
- 函数指针指针数组
- 数组指针、函数指针
- 指针&数组&函数指针
- 函数指针数组指针!
- node.js
- 高效加载 Bitmap
- C# 将 HTML 转换为图片或 PDF
- 各大OJ题目分类
- 杭电oj 题目1196 Lowest Bit
- 数组指针,指针数组和函数指针
- Sublime Text 3教程
- 解决数据库保存中文数据后变'???'
- hnust
- SpringMVC启动时报错:Unable to create a Configuration, because no Bean Validation provider could be found.
- 项目中Angularjs遇到的问题和优化总结
- NI/NDK开发指南(十)——JNI局部引用、全局引用和弱全局引用
- Qt使用connect函数时向slot传递参数
- java 二叉搜索树的后续遍历序列