指针
指针的概念
在内存中每一个数据都有一个地址,这个地址叫做指针。
用于储存这个地址的变量叫做指针变量。
只不过平时我们把指针叫做地址,指针变量叫做指针。
指针的操作方式
& 取地址符
获取数据的地址,多字节数据获取首地址
* 在定义指针时是一个标识符
在其他场景下表示指针指向内存空间里的数据
指针与变量的关系
#include<stdio.h>
int main(int argc, const char *argv[])
{
int a=100;
int *p=&a;
printf("a=%d &a=%p\n",a,&a); // a=100 &a=0x7ffdbf7f315c
printf(" *p=%d p=%p &p=%p\n",*p,p,&p); // p=100 p=0x7ffdbf7f315c &p=0x7ffdbf7f3160
return 0;
}
指针的内存大小
32位系统中 指针内存大小是4个字节;
64位系统中 指针内存大小是8个字节;
指针的运算符
算术运算符:+ - ++ --
赋值运算符:=
关系运算符:>= <= == !=
* 指针操作的是内存地址 指针的运算就是把地址当作变量来进行运算
因此不是同类型的指针变量运算毫无意义
指针与一维数组
数组名本身就是首地址
#include<stdio.h>
int main(int argc, const char *argv[])
{
int s[10]={0};
printf("s=%p &s[0]=%p\n",s,&s[0]);
//s=0x7ffd502a0ce0 &s[0]=0x7ffd502a0ce0
return 0;
}
因此 int *p=s;
p==s p==s[0] p+1==s[0+1]
指针和二维数组
数组名是数组的首地址,那么二维数组也是一个数组 但是二维数组有行和列两个[ ] [ ]
如果
s=[10][10]={0} ;
int *p=s ;
因为指针可以运算 那么p+1等于什么?
#include<stdio.h>
int main(int argc, const char *argv[])
{
int s[2][2]={0};
int *p=s;
printf("s=%p s[0][1]=%p s[1][o]=%p\n",s,&s[0][1],&s[1][0]);
printf("p=%p p++=%p\n",p,p+1);
return 0;
}
s=0x7ffc0375b100 s[0][1]=0x7ffc0375b104 s[1][o]=0x7ffc0375b108
p=0x7ffc0375b100 p+1=0x7ffc0375b104
p+1=是s[0][0+1] 如果要访问s[1][0] 也可以访问 p+3=s[1][0]
很麻烦 所以有数组指针
数组指针
本质上是个指针;
格式 数据类型 (*变量名)[列宽]
int (*p)[2]=s;
#include<stdio.h>
int main(int argc, const char *argv[])
{
int s[2][2]={0};
int (*p)[2]=s;
printf("s=%p s[0][1]=%p s[1][o]=%p\n",s,&s[0][1],&s[1][0]);
printf("p=%p p++=%p\n",p,p+1);
return 0;
}
s=0x7ffc26f06cf0 s[0][1]=0x7ffc26f06cf4 s[1][o]=0x7ffc26f06cf8
p=0x7ffc26f06cf0 p+1=0x7ffc26f06cf8
指针每次加1 就会加 数据类型*列宽 个单位;
相当于一个行指针 指定到行数 指向的是每行的头一个地址
如果想获取其他元素 可以用 * 变成列指针
#include<stdio.h>
int main(int argc, const char *argv[])
{
int s[2][2]={0};
int (*p)[2]=s;
printf("s=%p s[1][0]=%p s[1][1]=%p\n",s,&s[1][0],&s[1][1]);
printf("p+1=%p *(p+1)+1=%p\n",p+1,*(p+1)+1);
return 0;
}
s=0x7ffd103f6e00 s[1][0]=0x7ffd103f6e08 s[1][1]=0x7ffd103f6e0c
p+1=0x7ffd103f6e08 *(p+1)+1=0x7ffd103f6e0c
数组指针多用与函数传参二维数组时
指针数组
本质上是个数组 是一个保存元素都是指针的数组;
格式 数据类型 *数组名 [数组元素的个数]
指针和字符串
char s=“hello”; 这是把字符串常量 hello 赋值给了变量s
char *p=“hello”; 这是把char类型的指针 p 指向了字符串 hello 的地址
注意 字符串常量定义之后不可以更改
二级指针
是一个保存指针的地址的指针;
#include<stdio.h>
int main(int argc, const char *argv[])
{
int a=100;
int *p=&a;
printf("a=%d &a=%p\n",a,&a); // a=100 &a=0x7ffdbf7f315c
printf(" *p=%d p=%p &p=%p\n",*p,p,&p); // p=100 p=0x7ffdbf7f315c &p=0x7ffdbf7f3160
return 0;
}
指针p保存是变量a的地址 对p取地址得到的是 &p=0x7ffdbf7f3160
指针的类型是 int * (8字节) 需要用一个int *的指针变量来保存
格式
数据类型 * 指针变量名=&一级指针名; int **q=&p;
#include<stdio.h>
int main(int argc, const char *argv[])
{
int a=100;
int *p=&a;
int **q=&p;
printf("a=%d &a=%p\n",a,&a);
printf("p=%d p=%p &p=%p\n",*p,p,&p);
printf("q=%p *q=%p **q=%d\n",q,*q,**q);
return 0;
}
a=100 &a=0x7ffc0888b9c4
p=100 p=0x7ffc0888b9c4 &p=0x7ffc0888b9c8
q=0x7ffc0888b9c8 *q=0x7ffc0888b9c4 **q=100
一级指针只能用二级指针保存 二级指针只能用三级指针保存 ............
8字节用long 类型也能保存 只能保存地址的值 没办法用 * 取出里面的值
指针函数
是一个返回值为指针类型的函数
int * function(){
return 指针变量;
}
注意 不能返回局部变量的指针;
局部变量在函数运行结束的会释放,指针就成了野指针
可以返回
全局变量的指针变量;
static 关键字修饰的局部变量;
形参传递过来的指针变量;
函数指针
是一个指向函数调用的指针;
格式 返回值类型 (*指针名)(形参表);
#include<stdio.h>
void function(){
printf("我是function\n");
}
int main(int argc, const char *argv[])
{
void (*p)()=function;
function();
p();
return 0;
}
我是function
我是function
多用于回调函数
函数指针数组
是一个数组 每个元素都是指向函数的指针
格式 返回值(*指针名[ 元素个数] ) (形参表);
void( *p[2] )()={NULL};
p[1]=function1;
指向函数指针数组的指针
是一个指针 指向函数指针数组
格式
返回值类型 (* ( * 指针名 ) ) ( 形参表 )=数组名;
void (*(*q) )()=p;
截至————————————————————————————————------2022.12.11
如有错误 接受批评 并改正