c语言 指针集合
Posted 万物皆为二叉树
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c语言 指针集合相关的知识,希望对你有一定的参考价值。
指针集合
指针概念
- 什么是指针
在计算机科学中,指针(Pointer)是编程语言中的一个对象,利用地址,它的值直接指向(points to)存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为“指针”。意思是通过它能找到以它为地址的内存单元。 - 指针和内存的关系
- 代码表示
#include<stdio.h>
int main()
int a = 0x11223344; // a申请一块内存空间 同时获得该内存空间的编号
//内存空间用于存放a的数值0x11223344
int* p = &a; // 存放a的数值的内存空间编号存放在变量p
return 0;
总结 :
指针存放的是指向空间的内存编号
指针类型集合
字符型指针
字符型指针两种用途
- 存放一个字符的地址
#include<stdio.h>
int main()
char a = 'a';
printf("%d", a);
char* p = &a; //p存放的就是a的地址
return 0;
具体内存存储方式 戳这里动态内存分配
- 存放一个字符常量数组
#include<stdio.h>
int main()
char* p = "abcdef";
printf("%c\\n", *p); //打印结果可知 cha*p存放的任然是首地址
printf("%s\\n", p);
return 0;
注意 :
- 使用%s 打印传的首地址 碰到\\0就停止 无需解应用
- 该定义的字符数组为 加了const修饰的常量数组
我们在这里看一道百度的面试题
#include <stdio.h>
int main()
char str1[] = "hello bit.";
char str2[] = "hello bit.";
char *str3 = "hello bit.";
char *str4 = "hello bit.";
if(str1 ==str2)
printf("str1 and str2 are same\\n");
else
printf("str1 and str2 are not same\\n");
if(str3 ==str4)
printf("str3 and str4 are same\\n");
else
printf("str3 and str4 are not same\\n");
// 问 该出 输出是什么?
return 0;
结果
结果是显而易见的 作为const修饰的数组 他就成为一个常量,系统无需要为其开辟两个内存空间我们在vs2019 调试验证
str3 和str4虽然是指针 但是他们指向的地址却是一样的
可见 系统不会为相同的常量开辟两个空间。
整形指针
整形指针用来存放整形变量的地址的指针
#include<stdio.h>
int main()
int i = 0x11223344;
int* p = &i; //将i的地址编号存放在p中
return 0;
浮点数指针
浮点数使用方式同整形一致
但浮点数 存储方式与整形不同戳这里 浮点数动态内存分配
#include<stdio.h>
int main()
float a = 3.14;
float* p = &a;
printf("%f", *p);
return 0;
指针步长
指针步长与指针对应数据类型的大小一致
char*的指针走一步只能前进一个字节
数组指针
1.数组指针的基本使用
由打印结果 可知 数组指针的步长就是数组指针定义的数组 ·
2.数组指针在一维数组的使用
打印一个数组
#include<stdio.h>
int main()
int arr[10] = 1,2,3,4,5,6,7,8,9,10 ;
int(*parr)[10] = &arr;
for (int i = 0; i < 10; i++)
printf("%d ", *((*parr) + i));
printf("%d ", parr[0][i]);
printf("%d ", (*parr)[i]);
return 0;
我们在对arr和&arr 进行总结
接下来我们解读 parr *parr arr &arr 内存存放 以及 内存编号
- *((*parr)+i)) :
因为parr 存放的是整个arr的地址 对*parr解应用可得 *(arr+i)
arr 存放的首元素地址 相当于 &arr[0]
给arr 加i 就跳过i个元素 得到第0+i个元素的地址
对arr+i解引用 得到arr[0+i]的值 - parr[0][i] :
parr[0]=> parr指向了第0行的所有元素 =>对parr解引用就得到了第0行所有元素=>(*(parr+0)<==>arr)=>第0行的arr[i]元素。 - printf("%d ", (*parr)[i]) :
*(parr+0)<==>指针parr指向arr的0行
注意:
- 在使用数组指针时 [ ]中的数表示指针指向数组的的个数 不可空置
- parr 可以看做arr的二阶的指针
- 数组指针在一维数组中无明显效果 不建议在一维数组中使用
3.数组指针在二维数组中的使用
e.g 使用数组指针打印二维数组
void print(int(*parr)[5], int r, int c)
for (int i = 0; i < r; i++)
for (int j = 0; j < c; j++)
printf("%d ", *(*(parr + i) + j));
printf("\\n");
int main()
int arr[3][5] = 1,2,3,4 ,2,3,4,5,6,3,4,5,6,7 ;
print(&arr, 3, 5);
return 0;
函数指针
举例使用
#include<stdio.h>
void print(int x)
printf("%d", x);
int main()
int i = 12;
print(i);
void (*pf)(int) = &print;
return 0;
e.g 2
#include<stdio.h>
int Add(int x, int y)
return x + y;
int main()
int i = 9;
int k = 10;
int (*pf)(int, int) = &Add;
int ret=(*pf)(i, k);
printf("%d", ret);
return 0;
上例中 int (*pf)(int, int) = &Add;
中* 不可少 但 int ret=(*pf)(i, k);
但这个却可以改成int ret=(pf)(i, k);
甚至可以加任意*号 这是为什么呢
我们观察函数地址以及内存存放
我们发现 在vs2019编译器中函数的地址没有放在函数指针里面
我们在调试反汇编可看出 函数指针存的地址需要跳到另一个地址处 该地址存放着函数的指针 所以 函数指针很不安全 使用过程应该小心
接下来 我们研究两个经典案例
- 例1
(*(void (*)())0)();//如何解读??
然后在调用该函数 及是本行代码的旨意。
总结: 调用0地址处函数 该函数无参 返回值为void。
- 例2
void (*signal(int , void(*)(int)))(int);
去掉函数传参部分 就是函数返回类型 可见 函数返回类型任然是函数指针。
那么我们怎么简化这个函数声明呢。
我们可先定义一个 指针类型 pf
typedef void(*pf)(int);
注 : pf 不可写在外面 这是函数指针定义规则
那么
pf<==>void(* ) ( int );
pf signal(int, pf);
注意:
- 在vs编译器中函数指针存放的不是函数的地址,
- 使用函数指针时 其安全性有待提高。
- typedef 定义的函数指针 注意其书写格式
数组指针
数组指针概念
数组元素全为指针变量的数组称为指针数组,指针数组中的元素都必须具有相同的存储类型、指向相同数据类型的指针变量
数组指针和指针的关系
可以得出结论 指针数组是有一个个指针构成的 将函数指针存放在数组中就可得到函数数组。
一般函数指针
指针数组,含有10个指针元素 也就是说每一个元素都是指针。先是解析[]表示它是一个数组,然后*表示指针,int表示为int型指针m 即表示定义一个指针数组,含有10个int类型指针元素。
可以这样初始化:
for(int i=0; i<10;i++)
p[0] = &i; // 每个元素都是指针
- 与int * q
进行对比 int * q ; //表示 q是指向 int的一个指针,即只是一个指针。但是如果 q 指向一个数组的首地址,那么可以用 q[] 这样的形式来访问数组的元素。
如下:
int students[] = 101, 102, 103, 104, 105, 0, 0, 0, 0, 0, 201, 202,203, 204, 0, 0, 0, 0, 0, 0, 301, 302, 303, 0, 0, 0, 0, 0, 0, 0 ;
int * q = students;
3、对上面进行总结
指针是一个指向int的地址, 数值指针 是一个指向int* 值
辨析数组指针与指针数组 阿里面试题
#include<stdio.h>
int main()
int i = 2;
int a[4][4] = 0 ;
int* p;
int* q[4];
//p = a;
q[i] = a[i];
p = q[i];
p = &a[2][1];
return 0;
因为a是错误选项 所以将a注释后 调试观察
p作为一个普通指针 不能用二维数组对其赋值 应使用数组指针
可见此题a错误。
函数指针数组
- 函数指针数组:函数指针的一个用法出现在菜单驱动系统中。例如程序可以提示用户输入一个整数值来选择菜单中的一个选项。用户的选择可以做函数指针数组的下标,而数组中的指针可以用来调用函数
举例:
#include "stdio.h"
void fun1(void)
printf("fun1 \\r\\n");
void fun2(void)
printf("fun2 \\r\\n");
void fun3(void)
printf("fun3 \\r\\n");
int main()
int i=0;
void (*p1)(void)=NULL;
void (*p2)(void)=NULL;
void (*p3)(void)=NULL;
void(*p_arry[3])(void)=NULL,NULL,NULL;
p1=fun1;
p2=fun2;
p3=fun3;
p_arry[0]=p1;
p_arry[1]=p2;
p_arry[2]=p3;
for(i=0;i<3;i++)
(*(p_arry+i))();
printf("*************************\\r\\n");
p1();
p2();
p3();
return 0;
2. 函数指针数组是一个存放函数指针的数组 。本质也是数组
以上是关于c语言 指针集合的主要内容,如果未能解决你的问题,请参考以下文章