目录
指针用法及简单理解
一、概念
内存中每个字节的空间都会有一个编号,这个编号就是指针也叫作地址,保存指针的变量叫做指针变量。
只不过通常的情况下,我们常说的:
地址:说的是内存地址
指针:说的是指针变量
二、指针有关操作及理解
&: 获取变量的地址 在定义变量时。
*:在定义变量时,只起到一个标识作用,标识定义的是一个指针变量其他场景下,取操作都表示通过指针访问对应的地址上的数据
在64位系统中指针大小为8字节
在32位系统中指针大小为4字节
三、指针与变量关系及理解
int a=10;
//第一种给指针赋值的方法(初始化)
int *p=&a;
//第二种给指针赋值的方法(初始化)
int *p=NULL;
p=&a;
/*
p 可以看做一个用来保存地址的变量
*P 可以看做是操作p所保存地址的变量的内容
*/
简单点去理解指针:
把“a”看做一个仓库,既然是仓库就会有地址(&a),也能存放货物(10)。
指针可以看做是仓库雇佣的“工人”,既然雇佣了工人就要告诉工人仓库在哪,以操作那一种货物。
四、实例
#include <stdio.h>
int main(int argc, const char *argv[])
{
//内存中每个字节的空间都有一个编号,这个编号就是指针,也叫地址
//当程序执行到定义变量的语句时 操作系统会根据类型给变量分配空间
int a = 10;
//通过变量名可以获取到变量的地址
// & : 获取变量的地址 &a 取到的是变量的首地址 编号最小的那个
// %p 输出地址
printf("&a = %p\n", &a);
//常量没有地址可言
//printf("&100 = %p\n", &100);//错误的
//普通变量是可以 存储 变量的地址的
//但是一般 不会这么做
//因为 没法通过保存地址的变量取访问对应的内存空间
//下面例子 temp可以保存 a的地址 但是没法通过 temp 改变a的值
//long temp = &a;
//printf("temp = %p\n", temp);
//*temp = 1314;//错误的 普通变量不允许做 * 操作
//定义一个指针变量p 保存 变量a的地址的
//也称为 指针p 指向 a
//格式 数据类型 *指针变量名;
int *p = &a;
printf("p = %p\n", p);
//通过p是可以操作 a所在的内存空间的
*p = 1314;//*p 表示访问 p保存的地址中的数据
printf("a = %d\n", a);
//指针保存了变量的地址后 有下面的关系
//p <==> &a
//a <==> *p
printf("p = %p &a = %p\n", p, &a);
printf("*p = %d a = %d\n", *p, a);
//指针变量也是一个变量 也需要操作系统分配空间
printf("&p = %p\n", &p);
//指针只能保存已经分配给你的空间的地址
int *p2 = 0x123456;
//printf("p2 = %p\n", p2); //可以保存 但是不能操作
//*p2 = 520;//错误的
//指针如果没有初始化 指向是不确定的 因为存的是随机值
//这种指针叫做 野指针
//野指针是有害的 错误不可预知
//int *p3;//注意:代码中不要出现野指针
//指针变量的初始化
// NULL 空地址 0地址 NULL 本质 (void *)0
int *p4 = NULL; //不确定要指向谁的指针先让他指向NULL
//这种指针叫空指针
//对空指针的操作 一定会段错误
//*p4 = 1314;//段错误
return 0;
}
五、指针运算
指针的运算,本质就是,指针变量里面存的地址之间的运算。所以,运算的操作就是有限的了
指针之间可以做 算数运算 : +、 -、 ++、 --
关系运算 :>、<、>=、<=、==、!=
赋值运算 : =
注: 同种类型的指针之间做运算才有意义,不同类型的指针做运算是没有意义的。
#include <stdio.h>
int main(int argc, const char *argv[])
{
//指针类型 的作用
//决定了从指针指向的编号开始,可以操作几个字节的空间
//一般为了让指针操作的范围和指向的变量操作的范围一致
//都使用和变量类型一致的指针
int num = 1314;
int *ppp = #
//对于两个变量而言 地址运算没有意义 因为地址都是有操作系统分的 是随机的
//对数组来说 指针的运算是有意义的 因为数组成员在内存上是连续的
int s[5] = {10,20,30,40,50};
int *p2 = &s[0];
int *p3 = &s[2];
//两个指针做减法 差值 是相差的 指针的 数据类型的个数
//而不是相差的字节数
printf("p3 - p2 = %ld\n", p3 - p2);//2 相差两个 int
//指针的强制类型转换是 安全的
char *q1 = (char *)p2;
char *q2 = (char *)p3;
printf("q2 - q1 = %ld\n", q2 - q1);//8
//一个指针+ 或着 - 一个整数n
//表示: + 或者 - n*sizeof(指针的类型) 个字节
int *p4 = p2+4;//相当于 加了4 个int
printf("*p4 = %d\n", *p4);//50
//两个指针是可以做关系运算的 但是一般也是在数组成员的地址中
//比较大小才有意义 以大于为例 其他同理
if(p3 > p2){
printf("yes\n");
}else{
printf("no\n");
}
printf("--------------------\n");
int a = 10;
int b = 10;
int *hqyj1 = &a;
int *hqyj2 = &b;
if(hqyj1 == hqyj2){//比较的是 a和b的地址
printf("yes1\n");
}
if(*hqyj1 == *hqyj2){//比较的是 a和b的值
printf("yes2\n");
}
printf("--------------------\n");
//指针变量也是变量 变量之间是可以相互赋值的
int *p5 = NULL;
p5 = p2;//正确的
p5 = p3;//正确的
//注意下面的用法
int s2[5] = {10,20,30,40,50};
int *p = &s2[0];
int ret1 = *++p;
printf("ret1 = %d\n", ret1);//20 先算 ++p 然后对 ++p表达式的结果取 *操作
// ++p 表达式的结果 是+之后的值
printf("p = %p &s[1] = %p\n", p, &s2[1]);//相等
p = &s2[0];
int ret2 = *p++;
printf("ret2 = %d\n", ret2);//10 先算 p++ 然后对 p++ 表达式的结果取 *操作
// p++ 表达式的结果 是+之前的值
printf("p = %p &s[1] = %p\n", p, &s2[1]);//相等
return 0;
}