指针(Pointer)
定义:值为内存单元地址的变量。包含的是一个包含某特定数值的变量地址。
变量名:直接引用,
指针:简介引用——间接寻址(Indiretion)
用途:使得程序能够实现按引用在函数间传递参数。
指针变量的定义和初始化
声明:函数类型 *标识符;(*号只对后面定义的一个标识符起作用。)
可以被定义为指向任何类型的对象。
指针必须初始化
可以在定义指针时进行,也可以使用一个赋值语句。
NULL型:表示不指向任何对象。(NULL在一个头文件为<stddef.h>以及其他头文件,如<stdio,h>中定义的符号变量)。
0型:等价于初始化为NULL。首先被转化为一个适当类型的指针——唯一的可以直接赋值给指针变量的整数值。
地址型:使用&,*。
指针运算符
取地址运算符&(Address
operater):一元运算符,返回操作数的地址值。
操作数必须是一个变量
间接寻址运算符*(Indirection operater)(解引用运算符(Dereferencing operater),脱引用运算符):返回操作数指向的对象的值。
解引用(Dereferencing
a pointer)
致命错误:一个指针变量没有被初始化,或没有对它赋值使其指向内存中某一个确定的存储单元,就对这个指针变量解引用。——运行时——或意外地改写数据
按引用向函数传递实参
若想调用一个函数来修改实参,只需将实参的地址传递给函数
若期望接受一个地址(或一个单下标数组)作为实参,就必须先定义一个指针类型的形参来接收。
向函数传递指针
1.指向可变数据的可变指针(Non-constant pointer to
non-constant data)
*有最高访问权限
*含义:1.可以通过对指针进行解引用改写该指针所指向存储单元的数据,
2. 可以改写指针,使其指向其他的数据项
*用途:期望接收字符串实参的函数——处理(改写)字符串中的每个字符
*声明: char
*sPtr;(从右向左)
2.指向常量数据的可变指针(Constant pointer to
non-constant data)
*用途:
修改指针,使其指向任何类型的任何数据项
当需要将结构体数据传递给函数(自动按值),使用其以同时获得“按引用传递”的高效性,“按值传递”的安全性。——只需要复制结构体所在的内存空间的首地址。
声明:const
char
3.指向可变数据的常量指针(Non-constant pointer to
constant data)
*含义:内存空间不变,空间中的数据通过指针改写——数组名的默认——一个数组名就是一个指向数组起始元素的常量指针(数组中所有元素可以使用数组名和数组下标来访问和改写)。
*声明:int
*const
4.指向常量数据的常量指针(Constant pointer to
constant data)
*有最小的访问权限。
*含义:指向一个固定的内存单元,数据不可更改。
*传递给函数的数组元素只能以数组下标表示法读取
*声明:const
int *const
*传递数组的大小:传递一个指向数组头部的指针和一个指向数组尾部后面紧跟着的那个存储单元的指针
Sizeof 运算符
*含义:
计算数组(或其他数据类型)的字节长度——编译期执行。返回以size_t类型表示的该数组所占的字节总数。——只有用于真实的数组有效,运用于指向数组的指针无效。
指向指针时,返回该指针的大小,而不是该指针所指向的数据项的大小。
用途:确定数据类型,数组以及指针的大小。
指针表达式和指针算术运算
*运算符: ++,–,+,-。
*将指针对准一个数组
Vptr=v;
Vptr=&v[0];
加法(+):给整数乘以指针所指向对象的字节长度(取决于对象的数据类型)
++(–):使指针指向下一个数组元素
减法(-):只有作用于数组时,指针算术运算才有意义。
X=v2ptr-vptr 将二者之间的数组元素个数给X
*指针赋予指针:仅在类型相同时才可以
例外:指向void的指针(Pointer
to void)——可以表示任何指针类型的通用指针——void无法解引用
指针比较
*用途:1.比较存储于指针中的地址的大小——只有指向的是同一数组的元素才有意义。
判断指针是否是NULL
指针和数组
向函数传递数组时,不需要使用&运算符,——用数组名作为实参,C自动将数值在内存中的起始地址传递给函数(按引用)——传递的已经是地址。
不带下标的数组名就是指向数组第一个元素的指针
数组表示法
指针和数组的关系
1.一个数组名可以看作一个常量指针,
2.指针可以用于任何涉及数组下标的操作
*指针/偏移量表示法(pointer/offset natation)
*(bptr+3) *(b+3)
3代表针对一个指针的偏移量(offset)偏移量表示要引用数组中的一个元素,偏移量的值与数组的下标相同。*的优先级高于+
地址&b[3]可以被写成 bPtr+3
所以带下标的数组表达式都可以写成指针和偏移量的表示形式,可以将数组名当作指针,使得指针/偏移量表示法来表示数组元素。数组名始终指向数组的第一个元素——不可以修改。
*指针/下标表示法(pointer/index notation)
bptr[1]
指针数组
- 数组元素可以是指针,
*通常用于构造一个字符串的数组,数组的每一个元素都是一个字符串。
*字符串的实质:指向第一个字符的一个指针。
指向函数的指针(P234)
*含义:
包含一个函数在内存中的地址。函数名是执行该函数功能的程序代码在内存中的起始地址。
*作用
1.可以作为实参传递给函数,
2.作为返回值从函数返回,
3.存入数组,
4.赋值给其他函数指针。
Int (*函数名)(变量,变量)
函数名两边的()不可省略!
*关系:
对一个指向函数的指针解引用,就是调用其指向的函数,调用一个函数,可以将指向它的指针当作函数名直接使用。
*适用范围:
基于文本的菜单驱动的系统(提示用户通过键入一个数字,从菜单中选择一个选项。每个选项的功能由不同的函数来完成。指向每一个函数的指针存储在一个函数指针的数组中)
最小权限原则:
除非主调函数明确要求被调函数修改主调函数中实参变量的值,否则都应使用按值调研传递实参——防止主调函数中的实参被意外改写。
使用const 限定符——减少程序排错所需的时间。
给函数足够的权限,使其可以访问形参中的数据,完成特定的宫女,但绝不能给它过多的权限。
将某个函数的函数原型放在其他函数的定义中——限定这个函数的调用只能在包含其函数原型的函数中进行。
全局变量违反了“最小权限原则”