C-指针

    科技2025-06-09  41

    指针

    int i=1; int *p=&i;

    画出内存的图就是如下 内存里是没有P,i的。 p的值就是0x00f1, *p =*0X00f1 也就是取得 i的值为1

    转成汇编,就是lea rax,[rpb-0xc] 获取[rpb-0xc]处的内存地址放到rax中 然后放到[rbp-0x8] 就是最上面的那个图。 理解了这个后,很多指针的东西就能理解。

    指针加减

    由上面可知 int *p 实际上就是一个内存里存了另个内存的地址 p的话就是另个内存的地址的值,内存从0开始,如果是4g内存,就到4g结束 是数字相当支持加减。用的最典型就是数组的加减。如下

    int main(){ //规定了 arr就是数组的第一个元素的地址 int arr[]={1,2,3,4}; // arr不支持加减,而int *p=arr 就可以进行p++操作 int *p=arr; for(int i=0;i<4;i++){ //p+i就是移动了4个字节(int) printf("%d \n",*(p+i)); } return 0; }

    为何知道移动4个字节,因为定义int p 的时候指定了 int。 转成汇编如下: +58:[rbp-0x4] 的值付给ax , 由+49得知 一开始[rbp-0x4]为0。 +63:取得[ax4+0X0]的地址给了dx +71: 取得数组的第一元素的地址,也就是1的地址给了ax +75: ax+dx 也就是dx+ax个字节,ax=4 这就是回答上面的答案 +94:[rbp-0x4]+1 +98: 比较是否=3 +102:jle 如果小于的话,就跳到main+58的地方

    数组指针

    打印出下面的二维数组

    printf("---------------------------\n"); int s2_arr[3][4]={ {1,2,3,4}, {5,6,7,8}, {9,10,11,12} }; //定义了一个指向 int[4] 的指针 s2_p int (*s2_p)[4]=s2_arr; for(int i=0;i<3;i++){ for(int j=0;j<4;j++){ //由于*比+运算级别高,所以必须*(s2_p+i)表示取得指向第i行的首地址 //*(s2_p+i)+j表示第i行第j列的地址 //*(*(s2_p+i)+j) 取得表示第i行第j列的地址的值 printf("%d ",*(*(s2_p+i)+j)); } printf("\n"); } printf("---------------------------\n");

    打印结果 也可以写成如下

    printf("---------------------------\n"); int s2_arr[3][4]={ {1,2,3,4}, {5,6,7,8}, {9,10,11,12} }; int (*s2_p)[4]=s2_arr; int (*s2_p2)[3][4]=&s2_arr; //指针的指针,s2_p2指向了s2_arr的首地址 for(int i=0;i<3;i++){ for(int j=0;j<4;j++){ printf("%d ",*(*(*s2_p2+i)+j)); } printf("\n"); } printf("---------------------------\n");

    函数指针

    指向函数的指针

    实例1:

    /**********************************************/ /** 3.函数指针,指向函数的指针 /**********************************************/ #include <stdio.h> int add(int,int); int sub(int,int); //int (*)(int,int) 定义了一个函数指针,该函数有2个int输入,1个int return int calc(int (*)(int,int),int,int); int add(int p1,int p2){ return p1+p2; } int sub(int p1,int p2){ return p1-p2; } int calc(int (*p)(int p1,int p2),int i1,int i2){ //(*p)表示获取的函数的地址 //如果写成p(i1,i2); 也可以,但这样就变成了函数调用 return (*p)(i1,i2); } int main(){ int s3_p1; int s3_p2; char op; printf("请输入算式!"); scanf("%d%c%d",&s3_p1,&op,&s3_p2); switch(op){ case '+': printf("%d%c%d=%d \n",s3_p1,op,s3_p2,calc(add,s3_p1,s3_p2)); break; case '-': printf("%d%c%d=%d \n",s3_p1,op,s3_p2,calc(sub,s3_p1,s3_p2)); break; default : printf("无效算式!"); } }

    实例2:

    int add(int,int); int sub(int,int); int calc(int (*)(int,int),int,int); //如何解释这个定义 //参照c运算优先和结合性,()优先级最高,函数有2个(),优先级相同则参照结合性 //()的结合性从左到右,所以先(*select(char)) // int (*select(char))(int,int); int add(int p1,int p2){ return p1+p2; } int sub(int p1,int p2){ return p1-p2; } //函数指针作为参数 int calc(int (*p)(int p1,int p2),int i1,int i2){ //return p(i1,i2); return (*p)(i1,i2); } //函数指针作为返回值 int (* select(char op))(int,int){ switch(op){ case '+': return add; break; case '-': return sub; break; } }

    参考

    关于c的运算符优先性和结合性问题

    Processed: 0.011, SQL: 8