指针
无限弟归: 弟 弟 弟 . . . 弟 弟_{弟_{弟..._{弟}}} 弟弟弟...弟
本人水平有限,写这篇文章的时候有时候我自己有不是整太明白
希望大家带着批判的眼光看
有什么错误欢迎大家指出或与我讨论
一、指针和指针变量
指针就是地址
指针就是地址,地址就是指针
一个数据对象的内存地址称为该数据对象的指针
此处的地址不是机器的物理地址,而是虚拟地址
指针变量就是存放指针的变量
int a = 1;
int *p; //p is NULL
p = &a;
习惯上我们也将“指针变量”简称为“指针”
但大家心里一定要明白这两个指针的区别。
一个是真正的指针,它的本质是地址;
而另一个是指针变量的简称。
二、指针的基本使用
声明一个 i n t int int 类型的指针 p p p
int *p;
变量 p p p 先和 ∗ * ∗ 结合 ,说明 p p p 是一个指针变量
然后再和 i n t int int 结合,说明该指针类型是 i n t int int ,指向一个 i n t int int 型的变量
没有初始化的指针在c语言中被定义为NULL
再声明一个 i n t int int 型的变量 a a a
int a = 5;
pintf("%x\n",&a);
// &a : 0x60fefc
p = &a;
printf("%x\n",p);
// p : 0x60fefc
printf("%x\n",&p);
// &p: 0x60fef8
printf("%d %d",a,*p);
// 5 5
其中的 ∗ * ∗ 表示取指针指向的内容, * p p p 即 a a a 的值 5
一元运算符*是间接寻址或间接引用运算符,当它作用于指针时,将访问指针所指向的对象
& \& &运算符在这里表示 取地址, & a \&a &a 表示 变量 a a a 的地址
此处的地址都是以我自己的机器运行结果为例
p r i n t f printf printf 中的 %x 表示按十六进制
我们可以看到,指针变量 p p p 中存储的内容就是 变量 a a a 的地址
其中 a a a 和 ∗ p *p ∗p 的值是一样的
但是后者经过了两步,先读取 p p p 的内容(地址) ,再按照这个地址去寻找内存单元
变量名 | a a a | p p p |
---|---|---|
内容 | 5 | 0x60fefc |
地址 | 0x60fefc | 0x60fef8 |
类型 | i n t int int | i n t ∗ int\ * int ∗ |
三 、指针的运算
指针的 + - 运算符
我们之前经常使用的 数组 的 数组名
我们知道数组在内存空间开辟的是一段连续的空间
也可以看作一个指针
它指向整个数组的第一个元素的地址
指针与整型数的加减
int A[3] = {1,2,3};
// 数组名代表了第一个元素的地址
// 在内存中开辟了三个int型大小的空间并赋值为1,2,3
// (若在全局变量中声明的,则默认值为0,否则都是一些奇怪的数据(垃圾数据 ,可以用 int A[10] = {0};初始化
int *p = A;
printf("%x\n",A);
//0x60fef0
printf("%x\n",p);
//0x60fef0
printf("%d %d\n",A[1],p[1]);
//2 2
printf("%d %d\n",*(A+1),*(p+1));
//2 2
ElemType *p;
p = p + 1 p = p + 1 p=p+1
表示的是 p p p 的值(地址) 加上一个指针类型的大小
此处的 “ 1 1 1” ,相当于一个 s i z e o f ( E l e m T y p e ) sizeof(ElemType) sizeof(ElemType)
即
p = p + s i z e o f ( E l e m T y p e ) p = p + sizeof(ElemType) p=p+sizeof(ElemType)
E l e m T y p e ElemType ElemType 表示的是 指针类型
i n t ∗ p int *p int∗p , p p p 就是一个整形( i n t int int)的指针变量
那么两个指针变量做减法,结果会是什么呢
int A[3];
int *p = &A[0];
int *q = &A[2];
printf("%d",q - p);
结果会是 2
所以在输入数据的时候,可以这样写
int A[maxn];
for(int i = 0;i < n;i++){
scanf("%d",A+i);
}
和 s c a n f ( " % d " , & A [ i ] ) ; scanf("\%d",\&A[i]); scanf("%d",&A[i]); 的写法是一样的
指针的类型转换
int a = (1<<8) + 1; //a的最后9个bit 是 1 0000 0001
// (1<<8) + 1 == 2^8 + 1 == 257
char* q;
int * p;
p = &a; //给p赋值
printf("%x %d\n",p,*p);
//0x60fef4 257
q = (char*)p;
//将p 转换成char*类型再赋给 q,这个操作不会改变 p
此时,大家试想,q 和 q的内容是什么
printf("%x %d\n",q,*q);
//0x60fef4 1
我们发现了 q q q 和 p p p 的值是一样的,但是值却不一样 了
根据结果
我们可以知道,一个 i n t int int 型的变量占据了四个字节的空间
而 i n t int int 型的指针变量 p p p 指向了最低位的字节,然后读取四个字节的内容
而 q q q 指针 是 执行了语句 q = ( c h a r ∗ ) p q = (char *) p q=(char∗)p 后得到的 c h a r ∗ char* char∗ 型指针
他们的内容是一样的,但是由于 q q q 是 c h a r char char 型的指针变量
再读取内容时只读取了一个字节的内容 ( 0000 0001 )
malloc函数
例
int *p = (int*)malloc(4*sizeof(int));
m a l l o c ( n ) malloc(n) malloc(n)函数返回一个 v o i d ∗ void* void∗的指针,开辟了 n n n 个字节的空间
所以上述语句申请了4个 i n t int int型的空间,并返回了首地址,然后通过类型转换,转换成 i n t ∗ int* int∗ 再赋值给 p p p
四、指针的一些作用
可以实现一些数据结构,比如链表,二叉树之类的
可以更加灵活的对数据进行操作
写不下去了, o r z orz orz
大家有什么问题可以来问我
也可以自行上机进行验证
识别变量到底是个啥
int p;
int *p;
int p[3];
int *p[3];
int (*p)[3];
int **p;
int p(int);
Int (*p)(int);
int *(*p(int))[3];