什么是指针?
在计算机科学中,指针(Pointer)是编程语言中的一个对象,利用地址,它的值直接指向(points to)存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为“指针”。意思是通过它能找到以它为地址的内存单元。
指针是个变量,存放内存单元的地址。
对应到代码:
#include <stdio.h>
int main() {
int a = 10; //在内存中开辟一块空间
int *p = &a;//这里我们对变量a,取出它的地址,可以使用&操作符。
//将a的地址存放在p变量中,p就是一个之指针变量。
return 0;
}
总结:指针就是变量,用来存放地址的变量。(存放在指针中的值都被当成地址处理)。
一个小的单元到底是多大?(1个字节)
- 在32位的机器上,地址是32个0或者1组成二进制序列,那地址就得用4个字节的空间来存储,所以一个指针 变量的大小就应该是4个字节。
- 那如果在64位机器上,如果有64个地址线,那一个指针变量的大小是8个字节,才能存放一个地址。
总结:
- 指针是用来存放地址的,地址是唯一标示一块地址空间的。
- 指针的大小在32位平台是4个字节,在64位平台是8个字节。
指针和指针类型
这里我们在讨论一下:指针的类型我们都知道,变量有不同的类型,整形,浮点型等。那指针有没有类型呢?准确的说:有的。
当有这样的代码:
int num = 10;
p = #
要将&num(num的地址)保存到p中,我们知道p就是一个指针变量,那它的类型是怎样的呢? 我们给指针变量相应的类型。
char *pc = NULL;
int *pi = NULL;
short *ps = NULL;
long *pl = NULL;
float *pf = NULL;
double *pd = NULL;
这里可以看到,指针的定义方式是: type + * 。 其实: char* 类型的指针是为了存放 char 类型变量的地址。 short* 类型的指针是为了存放 short 类型变量的地址。 int* 类型的指针是为了存放 int 类型变量的地址。
那指针类型的意义是什么?
指针+整数:
#include <stdio.h>
#include <stdlib.h>
int main() {
int n = 10;
char *pc = (char*)&n;
int *pi = &n;
printf("%p\n", &n);
printf("%p\n", pc);
printf("%p\n", pc+1);
printf("%p\n", pi);
printf("%p\n", pi+1);
system("pause");
return 0;
}
运行结果:
总结:指针的类型决定了指针向前或者向后走一步有多大(距离)。
指针的解引用
#include <stdio.h>
#include <stdlib.h>
int main() {
int n = 0x11223344;
char *pc = (char *)&n;
char *pi = &n;
*pc = 0x55;//重点在调试的过程中观察内存的变化。
*pi = 0; //重点在调试的过程中观察内存的变化。
system("pause");
return 0;
}
总结: 指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)。 比如:char* 的指针解引用就只能访问一个字节,而 int* 的指针的解引用就能访问四个字节。
一级指针总结
1.做函数参数—间接修改普通变量
void setmem(int *p)
{
* p = 100;
}
int main()
{
int n = 10;
int *p = &n;
* p = 20;//--间接修改普通变量
setmem(p);//--间接修改普通变量
return 0;
}
2.做输入输出
#include <stdlib.h>
#include <stdio.h>
int showList(char *str)
{
if (str == NULL)
return 0;
else
return 1;
}
int main()
{
char *str = "hello world!";
if (showList(str) == 0)
printf("error!\n");
else
printf("%s\n", str);
system("pause");
return 0;
}
总的来说就是一句话:间接修改数据、传递地址。
下面是一级指针的主要用途:
- 可以利用一级指针改变函数外部的变量,还可以跨进程改变变量(外挂就是这么搞的)。
- 一级指针可以存储数组的首地址,并通过指针或者下标访问元素。
- 一级指针作为函数的返回值,返回地址;注意:不能返回指向栈的地址,因为函数执行完,变量就被回收了。
- 函数的参数有副本机制,传递实参时,新建一个变量,容纳传递过来的实参。特例:数组在函数参数中拒绝副本机制,数组作为参数时数组的首地址。
- return也有副本机制,返回值保存在CPU寄存器中,因此函数的返回值不能取地址。
- 为什么指针要有类型,因为类型可以让编译器知道如何解析,还有步长。
二级指针总结
指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里? 这就是二级指针 。
对于二级指针的运算有:
- *ppa 通过对ppa中的地址进行解引用,这样找到的是 pa , *ppa 其实访问的就是 pa
int b = 10;
*ppa = &b;//等价于 pa = &b;
- **ppa 先通过 *ppa 找到 pa ,然后对 pa 进行解引用操作: *pa ,那找到的是 a
**ppa = 30;
//等价于*pa = 30;
//等价于a = 30;
指针的本质就是地址, 那么几级指针也只是一个地址, 唯一不同的就是寻址的结果(*p)