指针相关内容总结
|
项目 |
格式 |
描述 |
代码案例 |
|
通用类型指针 |
void *指针变量名 |
可以指向任意类型的地址,但是使用是需要类型强转,多用于传参和返回 |
int main(int argc, const char *argv[]) { int a = 16; void *ptr = &a; printf("*ptr = %d\n", *(int *)ptr); return 0; } |
|
函数指针数组 |
存储类型 数据类型 (*函数指针数组变量名[常量表达式])(参数列表) 常量表达式:数组元素的个数 |
函数指针数组: 本质上是一个数组,数组的元素是函数指针 |
float Add(float a, float b){ return a + b; } float Sub(float a, float b){ return a-b; } float Mul(float a, float b){ return a*b; } float Div(float a, float b) { return a/b; } int main(int argc, const char *argv[]) {
float (*p1)(float, float)=Add; float (*p2)(float, float)=Sub; float (*p3)(float, float)=Mul; float (*p4)(float, float)=Div; float a=50,b=2; float (*p[4])(float, float)={Add, Sub, Mul, Div}; for(int i=0;i<4;i++) { // p[0]-->Add // Add(a, b); float s=p[i](a, b); printf("s=%.2f\n", s); } return 0; } |
|
函数指针 |
存储类型 数据类型 (*函数指针变量名)(参数列表) |
本质上是一个指针,用来指向函数的首地址,多用于回调函数 |
void Add(void) à void (*p)(void) = Add void Add(int a, float b) à void (*p)(int, float) = Add int Add() à int (*p)() = Add int Add(int a, float b) à int (*p)(int a, float b) = Add |
|
指针函数 |
数据类型 *函数名(参数列表) { 函数体; return 地址; } |
本质上是一个函数,返回一个地址. 注意: 不可以返回局部变量的地址 |
#include <stdio.h> #include <string.h> #include <stdlib.h> int *fun() //指针函数 { int a = 20, b = 10; int arr[2]; arr[0] = a; arr[1] = b; return arr; } // 注意: 上面这个函数并不能返回arr, 因为arr是局部变量, 函数结束时, arr就被系统回收了 //解决方法1: //把数组放到全局,延长生命周期的效果 int arr[2]; int *fun1()//指针函数 { int a=20,b=10; arr[0] = a; arr[1] = b; return arr; } //解放方式2: //把数据作为参数传递 int *fun2(int *arr)//指针函数 { int a=1,b=100; *arr=a; *(arr+1)=b; return arr; } //解决方式3: //把内存放到堆区malloc, 堆区的内存系统不会主动回收, 需要程序员手动回收, 这样就可以自己控制这部分内存的生命周期 //void *malloc(size_t size) //size_t size: 表示在堆区申请的内存大小 //void *: 申请成功返回堆区的首地址,失败返回NULL int *fun3() { int a = 20, b = 100; int *p = (int *)malloc(8); *p = a; *(p+1) = b; return p; } |
|
字符指针数组 |
char *指针数组名[常量表达式] |
本质上是一个数组,每个都是字符类型指针 |
#include <string.h> #include <stdlib.h> #include <stdio.h> int main(int argc, const char *argv[]) { char a[] = "abcd"; char b[] = "ABCD"; char c[] = "1234";
//char *p1 = a; //char *p2 = b; //char *p3 = c;
//字符指针数组指向变量的地址 char *p[3] = {a, b ,c};
*(*(p+1)+3) ='3'; //修改第1行,第3列的值 for(int i=0; i < 3; i++){ //puts(p[i]); //puts(*(p+i)); printf("p[%d] = %s\n", i, p[i]); printf("*(p+%d) = %s\n", i,*( p+i)); } putchar(10); char *q[3] = {"abcd", "ABCD", "1234"}; // *(*(q+1)+3) ='3'; // not ok //常量不能被修改 for(int i=0; i<3; i++){ printf("q[%d] = %s\n",i, q[i]); } return 0; } |
|
指针数组 |
存储类型 数据类型 *指针数组变量名[常量表达式] 常量表达式表示元素的个数 |
本质上是一个数组, 数组的元素是类型相同的指针 |
int a=1, b=2, c=3, d=4; // à int arr[4] int *p1=&a; int *p2=&b; int *p3=&c; int *p4=&d; int *p[4]={&a, &b, &c, &d}; // p[0] à&a // p[1] à&b // p[0] à&a // p[0] à&a |
|
数组指针 |
存储类型 数据类型 (*指针变量名)[常量表达式] int arr[2][3] = {1, 2, 3, 4, 5, 6}; int (*p)[3] = arr; |
本质上是一个指针,用来指向二维数组的地址,多用于传参和返回
|
#include <string.h> #include <stdlib.h> #include <stdio.h> int main(int argc, const char *argv[]) { int arr[2][3] = {11, 22, 33, 44, 55, 66}; int (*p)[3] = arr; //找第2行第3列元素 arr[1][2] //arr --> 第1行的行地址 //arr+1 -->第2行的行地址
//*代表降维 //*(arr+1) à第2行第1列地址 //*(arr+1)+2 à第2行第3列的地址 //*(*(arr+1)+2) --> 第二行第三列的值 //m行n列的元素 -->*(*(arr+m-1)+n-1) // //arr --> //*arr --> arr[0] //*(arr+1) --> arr[1] //*(arr+1) --> arr[i] //地址 for(int i=0; i<2; i++){ for(int j=0; j<3; j++){ printf("&arr[%d][%d] = %p\n",i,j, &arr[i][j]); //arr[i][j]是值,&取地址 printf("*(arr + %d) + %d = %p\n",i,j, *(arr+ i) + j); //arr 是首行地址, //arr + i 是 首行+i行地址, //*(arr + i) 是arr+i的首列地址, //*(arr + i) + j à首行+i行,首列+j列元素的地址 printf("arr[%d]) + %d = %p\n",i,j, arr[i] + j); //arr[i]表示第i行的首地址, //arr[i] + j; 第i行偏移j列元素的地址 putchar(10); printf("&p[%d][%d] = %p\n",i,j, &p[i][j]); printf("*(p+%d) + %d = %p\n",i,j, *(p+i)) + j; printf("p[%d] + %d) = %p\n",i,j, p[i] + j);
putchar(10); } putchar(10); } //值 for(int i=0; i<2; i++){ for(int j=0; j<3; j++){ printf("arr[%d][%d] = %d\n",i,j, arr[i][j])e //arr[i][j]是值 printf("*(*(arr + %d) + %d) = %d\n",i,j, *(*(arr+ i) + j)); //arr 是首行地址, //arr + i 是 首行+i行地址, //*(arr + i) 是arr+i的首列地址, //*(arr + i) + j --->首行+i行, 首列+j列元素的地址 //在地址上加*就是值 printf("*(arr[%d]) + %d) = %d\n",i,j,*(arr[i] + j)); //arr[i]表示第i行的首地址, //arr[i] + j; 第i行偏移j列元素的地址 //在地址上加*就是值 putchar(10); printf("&p[%d][%d] = %d\n",i,j, p[i][j]); printf("*(*(p+%d) + %d) = %d\n",i,j, *(*(p+i) + j)); printf("*(p[%d] + %d)) = %d\n",i,j, *(p[i] + j));
putchar(10); } putchar(10); } return 0; } ~ |
|
二维数组和指针 |
列:&arr[0][0] -->arr[0] -->&p[0][0] -->p[0] 行:&arr[0]-->arr--->&p[0]--->p 整个二维数组:&arr 偏移指针大小:&p--->&p+1 |
#include <string.h> #include <stdlib.h> #include <stdio.h> int main(int argc, const char *argv[]) { int arr[2][3] = {11, 22, 33, 44, 55, 66}; int (*p)[3] = arr; printf("column:\n"); printf("&arr[0][0] = %p\n", &arr[0][0]); printf("&arr[0][0] + 1 = %p\n", &arr[0][0] + 1); printf("&p[0][0] = %p\n", &p[0][0]); printf("&p[0][0] + 1 = %p\n", &p[0][0] + 1);
printf("arr[0] = %p\n", arr[0]); printf("arr[0] +1 = %p\n", arr[0]+1); printf("p[0] = %p\n", p[0]); printf("p[0] +1 = %p\n", p[0]+1); printf("row:\n"); printf("&arr[0] = %p\n", &arr[0]); printf("&arr[0] + 1 = %p\n", &arr[0]+1); printf("&p[0] = %p\n", &p[0]); printf("&p[0] + 1 = %p\n", &p[0]+1); printf("arr = %p\n", arr); printf("arr + 1 = %p\n", arr + 1); printf("whole 2d array:\n"); printf("&arr = %p\n", &arr); printf("&arr + 1 = %p\n", &arr + 1); return 0; } | |
|
多级指针 |
存储类型 数据类型**指针变量名 (*的个数任意) |
一级指针存储普通变量的地址 二级指针存储一级指针的地址 三级指针存储二级指针的地址 |
#include <string.h> #include <stdlib.h> #include <stdio.h> int main(int argc, const char *argv[]) { int a = 10; int *p = &a; int **q = &p; int ***m = &q; //值 printf("a=%d, *p=%d, **q=%d, ***m=%d\n", a, *p, **q, ***m); //a 地址 printf("&a=%p, p=%p, *q=%p, **m=%p\n", &a, p, *q, **m); //p 的地址 printf("&p=%p, q=%p, *m=%p\n", &p, q, **m); //q的地址 printf("&q=%p, m=%p\n", &q, *m); //m的地址 printf("&m=%p\n", &m);
return 0; } |
|
指针和字符数组 |
char str[]="hello"; char *p=str; |
#include <string.h> #include <stdlib.h> #include <stdio.h> // //字符指针指a向字符数组的地址 // int main(int argc, const char *argv[]) { char str[20]="hello"; char *p=str; //p-->str gets(str); puts(str); // 1.指针可以替换字符数组的使用 gets(p); puts(p); // 2.指针指向字符数组可以修改 *(p+1)='E'; puts(p); // 3.不同的字符数组存储相同字符串,数组地址不同 char a[]="1234"; char b[]="1234"; printf("a=%p b=%p\n",a,b); char *pstr = "hello";//p指向字符串常量hello的首地址 // a.指针指向字符串常量不可以修改,段错误 // *(p+1)='E'; // puts(p); // 2.不同的指针指向同一个字符串常量,则地址一样 char *qstr = "hello"; printf("p=%p\n q=%p\n",p,q); // b.字符指针指向字符串常量的地址 return 0; } | |
|
一维数组和指针 |
数据类型 *指针变量名=数组名 int arr[] = {11,22,33}; int *p=arr; |
一维数组名表示数组的首地址,既第一个元素的地址, 数组名是常量不可自增或自减 &arr[0]--->arr--->&p[0]--->p 偏移一个元素字节大小 &arr 偏移整个一维数组 &p 偏移一个指针字节大小 地址等价关系: &arr[i]à &p[i]à arr+Ià p+ià p++ 值等价关系: arr[i]à p[i]à *(arr+i)à *(p+i)à *p++ |
#include <string.h> #include <stdlib.h> #include <stdio.h> int main(int argc, const char *argv[]) { int arr[] = {11, 22, 33, 44}; int *p = arr; // printf("&arr[0] = %p\n", &arr[0]); printf("&arr[0] + 1 = %p\n", &arr[0] + 1); printf("arr = %p\n", arr); printf("arr + 1 = %p\n", arr + 1); printf("&arr = %p\n", &arr); printf("&arr + 1 = %p\n", &arr + 1);
printf("&p[0] = %p\n", &p[0]); printf("&p[0] + 1 = %p\n", &p[0] + 1); printf("p = %p\n", p); printf("p + 1 = %p\n", p + 1); printf("&p = %p\n", &p); printf("&p + 1 = %p\n", &p + 1); return 0; } |
|
指针的运算 算数运算 |
+ - ++ -- int a=10; int *p=&a; a: 值 &a:a地址,4字节的首编号 p:a地址,4字节的首编号 *p: a的值 &p: p的地址,8字节的首编号 |
+ int a=10;int *p=&a
- int a=10;int *p=&a
++ 只能对变量++运算 int a=10; &a是常量,不可以自增 int arr[]={11,22,33}; int *p=arr;
-- 和++类似 | |
|
算数运算 赋值运算 |
= += -= |
= int a=10; int *p=&a
+=
| |
|
算数运算 关系运算 |
int a=10; int b=20; 一般适用于数组,数组的地址是连续 |
| |
|
解引用和取地址 |
*: 解引用 &: 取地址 |
*:乘法,标识符,取值 &:逻辑与,按位与,取地址 int a=100; int *p=&a; *p=a=100 p=&a 带*表示值,不带*表示地址 *和&属于逆运算 值:a--> *p--> *&a--> *(&a) 地址:&a--> p--> &*p--> &(*p) | |
|
指针变量的定义以及初始化 |
1.指针的类型和地址对应的数据类型建议保持一致(常用) int a=100; int *p=&a; double b=2.5; double *q=&b; 2.指针的类型和地址的类型不一致(不常使用),实际是小端存储 int a=4626; char *p=&a; *p=18 3.可以使用已经初始化的指针变量为另一个指针变量初始化 int a=100; int *p=&a; int *q=p; 4.指针未初始化,不可以直接使用,否则称为野指针 野指针:访问非法的内存空间 int *p;//未初始化的指针,计算机会随机指向内存 5.当指针不清楚指向谁的地址时,指向NULL int *p=NULL; NULL:表示的0号地址,该地址不可以使用 6.指针的错误初始化 int a = 100; int *p = a; × not ok int *p = 100; ×not ok 7.不要使用静态类型的指针指向动态类型的变量地址 静态类型的内存先分配,动态类型的内存后分配 int a; static int *p=&a; × not ok | ||
|
指针的字节大小 |
指针的大小和操作系统有关,和数据类型无关 64位操作系统,指针8字节 32位操作系统,指针4字节 | ||
|
指针变量的定义 |
存储类型 数据类型 *指针变量名; |
3.*: 指针标志 4.指针变量名: int *p float *p char *p void *p
int a=100; int *p=&a; | |
该博客主要对C语言中指针相关内容进行总结,聚焦于信息技术领域中C语言编程里指针这一重要知识点。
1万+

被折叠的 条评论
为什么被折叠?



