硬核干货!指针!!!(6)

10 篇文章 0 订阅
10 篇文章 0 订阅

指针

指针即内存地址!
指针即内存地址!
指针即内存地址!

一:内存地址(虚拟内存)

(1)程序对内存地址进行编号[0,4G] (本质上是一个整数)
(2)保存一个地址需要4字节的空间
(3)sizeof(指针) == 4

seziof(char *) == 4字节
seziof(short *) == 4字节
seziof(int *) == 4字节
seziof(float *) == 4字节
seziof(double *) == 4字节
任何指针求seziof都是4个字节

二:指针变量

如果需要保存地址,就需要有变量
变量:标识内存区域中的一个地址
指针变量:能够保存地址

  1. 指针变量的定义
    数据类型 * 变量名;
 int * p;    //int * 是一个整体,表示类型为指针类型,int表示指针变量保存的是整数类型数据的地址
 int *p1,p2; //p1是 int * 类型 ,p2是int类型
 int *p3,*p4;//p3和p4都是 int * 类型
  1. 指针变量的初始化

(1)野指针:未初始化的指针变量称为 野指针(非常危险)

注意:
在编程过程中,一定要杜绝 野指针
如果对野指针取 * 运算,可能会得到意想不到的数据,也可能直接导致程序崩溃

(2)空指针:保存NULL的指针变量称为空指针

注意:
空指针不能取 * 运算
所以经常用 指针变量!=NULL 来判断是否可以进行*运算

如果定义的指针变量暂时不知道存储哪个地址,可以初始化为NULL(空指针), 代表内存0地址
一般用NULL来判断一个指针是否指向有效的内存

判断指针类型是否可以进行 * 运算:

if(指针变量 != NULL){
   *指针变量
  }
  1. 指针变量的操作

(1)对于任何变量都可以进行& (取地址运算符)
(2)对于指针变量而言,可以进行* (取值运算符)

 int n = 10;
 int *p = &n;  //指针变量保存的是 &n  ,n变量的内存地址
 
 *p == *(&n) == n
 *p = 119;   //相当于 n=119;
 
 int m = 20;
 p = &m;  //改变了指针变量p的值
 
 p = xxx;  //是对指针变量赋值  改变指针的指向
 *p = yyy; //是对指针变量所保存的内存地址里那个内存数据的赋值

注意:连续在一起的运算符*& 和 &* 是可以相互抵消的 。

(3)[ ] 下标运算符

int arr[10];
arr[i] == *(arr+i) == *(i+arr) == i[arr]
&arr[0] == &(*(arr+0)) == &(*arr) == arr
arr[0] == *(arr+0) == *arr

数组名,代表 数组首元素的地址
&arr 和 arr ,显示的地址是一样的,但是类型不一样

   int arr[10];
   arr + 1;  //偏移了4个字节   arr首元素的地址  每+1 偏移了一个元素的内存地址
   &arr + 1; //偏移了40个字节  &arr数组的地址   每+1 偏移了整个数组的内存地

(4)+ - 指针加减法
指针 + 1 :其实是加了一个“单位”长度的字节数 单位的字节数取决于指针的类型

char *    单位: 1字节
short *          2字节
int *            4字节
float *          4字节
double *         8字节

(5)*p++ 和 (*p)++
*p++ 表达式的结果是 *p 的结果,然后 p=p+1
(*p)++ 表达式的结果是 *p 的结果,然后 *p=*p+1

(6)形参:int arr [ ] 或 int arr [n] 实际上都相当于 int *arr

void func(int arr[]){   //在函数内部获取不到数组长度,所以必须通过参数传进来
    sizeof(arr) == 4
   }
 //数组名在传递过程中,退化为一个指针,所以数组在传递时需要传递数组的长度

(7)万能指针:void *

void的作用:
① 函数返回值类型 表示函数没有返回值
② 函数参数列表 表示函数不能接收任何参数
③ void * 万能指针

不同类型的指针之间,如果进行赋值,会报警告
任何类型的指针(地址)都可以赋值给 void * 指针变量
任何类型的指针都可以有 void * 相互转换且不报警告

  1. 指针的功能

C语言函数的传参方式是值传递的方式
(实参的值赋值给形参,修改形参的值并不影响实参的值)
C语言函数传递内存地址,在函数里面通过修改该内存地址里面的数据达到修改实参的目的

 int n = 110;   //声明一个变量 分配内存 内存中的数据为110  用n标识   
 int *p = &n;   //声明一个指针变量  分配内存   内存中存储的数据为   变量n的地址
 *p = 1;        // *p 取得  *(&n)   n   修改n的值为1
 int m = 119;    
 p = &m;        //修改p变量的值   
 *p = 9527;     // *p    *(&m)   m     修改m的值为9527
 int x = 0x12345678;
 char *p = (char *)&x;    // 强制转换 x的类型变为char

利用指针来交换两数的值:

//不要指针,只交换形参字节的值  根本就不影响实参
void swap_0(int a,int b){
 int t = a;
 a = b;
 b = t;
}
//正确 交换了*pa和*pb的值 ,实参的值改变
void swap_1(int *pa,int *pb){
 int t = *pa;
 *pa = *pb;
 *pb = t;
}
//交换了pa和pb的值  pa和pb所保存的那两个地址里面的数据没有交换过
void swap_2(int *pa,int *pb){
 int *p = pa;
 pa = pb;
 pb = p;
} 
//*p是野指针  非常危险
void swap_3(int *pa,int *pb){
 int *p;               // int *p = *pa;  虽然只是警告 但是意义是完全不同的
 *p = *pa;
 *pa = *pb;
 *pb = *p;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值