首页 > 编程知识 正文

r语言指针,st语言指针

时间:2023-05-04 04:17:08 阅读:250759 作者:4569

指针集合 指针概念指针类型集合字符型指针整形指针浮点数指针指针步长数组指针函数指针 数组指针概念数组指针和指针的关系一般函数指针函数指针数组

指针概念 什么是指针
在计算机科学中,指针(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("%cn", *p); //打印结果可知 cha*p存放的怡然的黑米是首地址 printf("%sn", p);return 0;}

注意 :

使用%s 打印传的首地址 碰到就停止 无需解应用该定义的字符数组为 加了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 samen"); else printf("str1 and str2 are not samen"); if(str3 ==str4) printf("str3 and str4 are samen"); else printf("str3 and str4 are not samen"); // 问 该出 输出是什么? 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 rn"); } void fun2(void){ printf("fun2 rn"); }void fun3(void){ printf("fun3 rn"); }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("*************************rn"); p1(); p2(); p3(); return 0; }2. 函数指针数组是一个存放函数指针的数组 。本质也是数组
Git-查找回购中哪些应用已更改云内存 监控告警 UMem RedisUCloud云社区见缝插针游戏的实现途径网络短信发送平台有哪些?JavaScript二叉树及各种遍历算法详情UsinguseState()withanobjectasstate

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。