C语言指针——基础知识理解

目录

前言:

(1)内存是如何编址的?

 (2)如何对变量进行寻址?

直接寻址:直接到变量名标识的存储单元读取变量的值——&

间接寻址:通过存放变量地址的其他变量访问该变量(通过其他变量间接找到变量的地址读取变量的值——*)

关于直接寻址的两个问题:

 (3)用什么类型的变量来存放变量的地址?——指针类型

(4)指针究竟指向了哪里?——指针变量初始化

未初始化带来的危害:

(5)空指针: 

 (6)指针变量与变量的地址的区别:

 (7)如何访问指针指向的存储单元中的数据?

 (8)指针的简单使用

典型实列:两数互换

(9)什么是函数指针?

定义函数指针常见错误: 

 (10)函数指针的应用:

 (11)总结:


前言:

强转与指针,并称C语言的两大神器,用好了可呼风唤雨,威力无比,用不好也会伤及自身
理解指针要从变量的地址谈起

(1)内存是如何编址的?

  • 内存中的每个字节都有唯一的编号(地址)(如同街道的门牌号),内存地址按字节编号,其字长一般与主机相同, 32位机使用32位地址,最多支持232字节内存(4G )
  • 地址是一个无符号整数0开始,依次递增。在表达和交流时,通常把地址写成十六进制数

 (2)如何对变量进行寻址?

  • 直接寻址:直接到变量名标识的存储单元读取变量的值——&

  • 间接寻址:通过存放变量地址的其他变量访问该变量(通过其他变量间接找到变量的地址读取变量的值——*)

 

  • 关于直接寻址的两个问题:

问题一、
int i;
scanf("%d", i); /* 这样会如何?*/

的值被当作地址。如i值为100,则输入的整数就会从地址100开始写入内存 

问题二
char c;
scanf("%d", &c); /* 这样呢?*/

输入数据以int的二进制形式写到c所在的内存空间。c所占内存不足以放下一个int,其后的空间也被覆盖

 (3)用什么类型的变量来存放变量的地址?——指针类型

  • 指针类型为4个字节大小 
  •  指针变量:具有指针类型的变量
  • 指针变量基类型:指针变量指向的数据类型,称为基类型(指针变量只能指向同一基类型的变量,否侧会引起warning)
int *pa;//定义的一个可以指向整型数据的指针变量
        //*号:表示pa是一个整型指针变量
//定义之后就可以用它保存一个整型变量的地址了
//告诉编译器,pa是一个指针变量,占4字节内存,需要用一个int型变量的地址给它赋值,

(4)指针究竟指向了哪里?——指针变量初始化

  • 使其具体的指向某一个变量
int *pa = &a;//指针变量初始化 //等价于int *pa;pa=&a

未初始化带来的危害:

  • 指针变量未被初始化,意味着指针变量的值是一个随机值,我们无法预知它会指向哪里,它很可能会乱指一气。使未初始化的指针变量是初学者常犯的错误,其带来的错误隐患是非常严重的。在不确定指针变量究竟指向哪里(也许是一个只读的或者不可访问的存储区,例如待执行的机器指令所在的代码段)的情况下,就对指针变量所指的内存单元,进行写操作,将会给系统带来潜在的危险,严重时还会导致系统崩溃
  • 如果你不知把它指向哪里,那就指向NULL
    int  a = 0, b = 1;
    char c = 'A';
    int *pa = NULL, *pb = NULL; 
    char *pc = NULL;          

(5)空指针: 

指针:值为NULL的指针,即无效指针
既然0NULL)用来表示空指针,那么空指针就是指向地址为0的单元的指针吗?
答案:不一定
  • Þ每个C编译器都被允许用不同的方式来表示空指针
  • Þ并非所有编译器都使用0地址
  • Þ某些编译器为空指针使用不存在的内存地址
  • Þ硬件会检查出这种试图通过空指针访问内存的方式

 (6)指针变量与变量的地址的区别:

 (7)如何访问指针指向的存储单元中的数据?

——指针的解引用:引用指针指向的变量的值,修改指针变量pa所指向的变量的值(修改存储单元中的数据)

 (8)指针的简单使用

典型实列:两数互换

  • 按值调用:普通变量作函数参数—按值调用 实参的值不随形参值的改变而改变
  • 按地址调用:指针做函数参数—按地址调用 为了在被调函数中修改其无法直接访问的实参的值

 

 注意:某些编译器检查实参和形参的数据类型是否匹配,不匹配则给出警告;另一些编译器直接将实参的值当作地址值,产生非法内存访问,导致程序异常终止

 

(9)什么是函数指针?

函数指针就是指向函数的指针变量,指向函数的指针变量中存储的是一个函数在内存中的入口地址

通过前面的学习可以知道:一个数组名其实就是存储数组第一个元素的内存地址。同理,一个函数名就是这个函数的源代码在内存中的起始地址

定义格式:数据类型(*指针变量名)(形参列表);

列如:若有函数原型为:int Fun (int a , int b);

           则可定义函数指针: int  (*f) (int,int)  ; f=Fun;就是让f指向函数Fun()

——编译器将不带()的函数名解释为该函数的入口地址

——函数指针变量存储的是函数在内存中的入口地址

定义函数指针常见错误: 

 (10)函数指针的应用:

实列一:编写通用性更强的函数

 典型实列二:编写通用的排序函数——编写实现升序和降序排序

 (11)总结:

——指针变量 :

  •  指针类型的变量,保存地址型数据

——指针变量与其他类型变量的共性:

  • 在内存中占据一定大小的存储单元(通常4个字节)
  • 先定义,后使用

——特殊性

  • 指针变量中保存的内容只能是地址(变量或函数的地址)
  • 必须初始化后才能使用,否则指向不确定的存储单元
  • 只能指向同一基类型的变量
  • 可参与的运算:加、减整数,自增、自减、关系、赋值

——指针变量

  • 定义不同基类型的指针,是明确指针指向单元的内容是什么
  • 初始化的目的,是明确指针指向了哪里

——使用指针变量的基本原则

  • 明确指针指向了哪里
  • 明确指针指向单元的内容是什么
  • 永远不要使用未初始化的指针变量
  • 一个(xx型)的指针指向一个(xx型)的变量

——指针的一个重要应用之一

  • 作函数参数,向函数传递变量或函数的地址

——指向变量的指针,作函数参数

  • 按地址调用,传递变量在内存中的地址(用取地址运算符
  • 被调函数根据该地址读写它不能直接访问的变量的值(用间接寻址运算符,指针的解引用)

——指向函数的指针,作函数参数

  • 按地址调用,传递函数在内存中的入口地址(函数名)
  • 被调函数根据传入的不同地址调用不同的函数
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值