基本问题
在计算机中,所有的数据都是存放在存储器中的,不同的数据类型占有的内存空间的大小各不相同。内存是以字节为单位的连续编址空间,每一个字节单元对应着一个独一的编号,这个编号被称为内存单元的地址。比如:int 类型占 4 个字节,char 类型占 1 个字节等。系统在内存中,为变量分配存储空间的首个字节单元的地址,称之为该变量的地址。地址用来标识每一个存储单元,方便用户对存储单元中的数据进行正确的访问。在高级语言中地址形象地称为指针。
地址与指针
指针相对于一个内存单元来说,指的是单元的地址,该单元的内容里面存放的是数据。在 C 语言中,允许用指针变量来存放指针,因此,一个指针变量的值就是某个内存单元的地址或称为某内存单元的指针。
变量及其定义
指针变量是存放一个内存地址的变量,不同于其他类型变量,它是专门用来存放内存地址的,也称为地址变量。定义指针变量的一般形式为:类型说明符*变量名。
类型说明符表示指针变量所指向变量的数据类型;*表示这是一个指针变量;变量名表示定义的指针变量名,其值是一个地址,例如:char*p1;表示 p1 是一个指针变量,它的值是某个字符变量的地址。
变量与其指向的对象的关联
<pre data-lang="clike">#include <stdio.h> //测试环境: Windows 10 Pro x86(32位)//打印的变量(i或者p)的地址可能每次都不一样int main(int argc,char** argv){ int i = 0x12345678; int* p = &i; printf("0x%08x \n", i); //打印结果: 0x12345678 printf("0x%08x \n", &i); //打印结果: 0x004ffed0 printf("%d \n", sizeof(i)); //打印结果: 4 printf("0x%08x \n", p); //打印结果: 0x004ffed0 printf("0x%08x \n", &p); //打印结果: 0x004ffecc printf("%d \n", sizeof(p)); //打印结果: 4 // 指针变量p指向的对象是变量i // 1.指向的对象变量i的地址是&i(0x004ffed0) // 2.指向的对象变量i的类型是int // 3.指向的对象变量i的内容是0x12345678 // 4.指针变量p本身的地址是&p(0x004ffecc) // 5.指针变量p本身的类型是int* // 6.指针变量p本身的内容是&i(0x004ffed0) return 0;}
从示例代码打印结果可以看出,指针变量p存储的内容就是其所指向的变量i的地址。指针变量p本身也是一个变量,也需要占据存储空间(32位系统下占4个字节),同样也有地址。
运算符
- & 取址运算符
功能:返回变量的内存地址(升一级)4
- * 取值运算符
功能:访问指针指向的变量(降一级)4
指针运算
- 指针±数值:p±n等价于p±n*c 。
- 指针-指针:结果为两指针所指向地址间数据的个数。
- 指针 比较 指针:产生的结果为 0(假)和 1(真)。4
注意事项
不允许把一个数赋予指针变量
不允许把一个数赋予指针变量,故下面的赋值是错误的。例如:
分析:前面例子中定义了一个指针变量 pointer,但是不能直接把 200 赋值给指针变量 pointer。后面的例子中定义了一个整型变量 a,并赋初始值为 200,又定义了一个指针变量 pointer,这个变量指向整型数据,pointer 中只能用来存放整型变量的地址,而不能直接把整型变量a赋值给这个指针变量 pointer。所以可以把a的地址赋值给 pointer;应改成:
改变形参不代表改变实参
不能企图通过改变指针形参的值而使指针实参的值改变。例如下面是错误的:
字符串指针
字符串指针指向的是一个字符串,例如下面是错误的:
分析:string1是一个指针变量,指向字符串"I love China",指针变量 string1 存放的是这个字符串的首地址。所以输出的是一个字符串,应改写成 printf(“%s\n”,string1);
调用函数指针
函数指针变量的调用,以下是错误的:
分析函数指针变量不能进行算术运算,这是与数组指针变量不同的。数组指针变量加减一个整数可使指针移动指向后面或前面的数组元素,而函数指针的移动是毫无意义的。函数调用中 “(*指针变量名)” 的两边的括号不可少,其中的 “ * ” 不应该理解为求值运算,在此处只是一种表示符号。要把“ z=*pomax(x,y);”改成“ z=(*pomax)(x,y);”。
信息工程
C语言,在1972年开发Unix操作系统时,丹尼斯里奇和肯汤姆逊设计了C语言。C语言不完全是里奇突发奇想而来,他是在肯·汤普逊发明的b语言的基础上进行设计。把C语言作为程序员的编程工具是它设计的初衷,因此它的主要目标是成为一种有用的语言。作为面向过程抽象化的通用编程语言,C语言在底层开发中得到了广泛的应用。C语言可以进行简单地编译和处理低级内存,是一种高效的编程语言,它只产生少量的机器语言,可以在没有任何运行环境支持的情况下运行。
函数是执行特定任务的独立程序代码单元。函数的结构和用法已经被C语言的语法规则定义了。函数在C语言中的细节略有不同。某些函数执行操作,如printf( ) 的作用是将数据打印在屏幕上显示出来,而一些函数则查找直接程序以供使用,如strlen( ),向程序返回指定字符串的长度。
指向函数的指针
程序编译后,每个函数都有执行第一条指令的地址即首地址,称为函数指针。函数指针即指向函数的指针变量,要间接调用函数可以使用指针变量来实现。
int(*pf)(int, int);
通过将pf与括号中的“ * ”强制组合组合在一起,表示定义的pf是一个指针,然后与下面的“ ( ) ”再次组合,表示的是该指针指向一个函数,括号里表示为int类型的参数,最后与前面的int组合,此处int表示该函数的返回值。因此,pf是指向函数的指针,该函数的返回值为int。函数指针与返回指针的函数的含义大不相同。函数指针本身是一个指向函数的指针。指针函数本身是一个返回值为指针的函数。
float(*p)(float x,float y);定义了一个指向函数的指针变量。首先c=(*p)(a,b);语句:因为指针p储存的是max函数的首地址,(*p)(a,b) 就相当于 max(a,b),函数返回较大值。其次c=(*p)(a,b);语句:因为指针p储存的是 min函数的首地址,(*p)(a,b) 也就相当于min(a,b),函数返回较小值。
指针变量的初始化
通过赋值语句初始化指针变量
C语言中指针初始化是指给所定的指针变量赋初值。
野指针
C语言中指针初始化是指给所定义的指针变量赋初值。指针变量在被创建后,如果不被赋值,他的缺省值是随机的,它的指向是不明确的,这样的指针形象地称为“野指针”。野指针是很危险的,容易造成程序出错,且程序本身无法判断指针指向是否合法。
指针变量初始化时避免野指针的方法:可以在指针定义后,赋值NULL空值,也可写成如下形式:
p=0或p='\0'
这两种形式和p=NULL是等价的
上面两行代码的含义是,指针变量p被赋值为空。虽然定义了一个指针变量,但是它并不指向任何存储空间。