由于变量在内存中所占的存储空间大小不一,为了便于对变量地址的访问,将变量存储单元的起始地址定义为变量的地址。在变量定义完成后,这些变量在内存中就具有了唯一的存储空间,也就具有了唯一的变量地址,可以通过变量的地址对其进行访问。
变量存储空间、变量地址与变量内容的关系就好像是仓库、仓库号与货物的关系。
通常情况下,可以直接通过变量名对变量内容进行访问,而无需知道变量在内存中的地址,系统会自动将访问转换为对内存单元的访问,这种通过变量名来对变量存储单元进行访问的方式称为“直接访问”。
C语言还支持对变量的内存单元进行“间接访问”。这种访问形式,允许将变量的地址赋给另一个特殊的变量,程序中可以利用这个特殊的变量来访问变量的内存单元。这个特殊变量称为指针。也就是说通过指针访问内存单元叫做间接访问。
指针的定义:指针变量就是用来存放内存地址的变量。
定义方式:
类型 *变量名 /*定义单个指针变量*/
类型 *变量名1,*变量名2…… /*定义多个同类型的指针变量*/
需要注意的是,定义指针变量时,每个指针变量前都要加 * 这个符号。指针变量的值只能是内存中存在的一个地址,而不是一个任意的整数。
int *pi; /* pi 是一个整型指针变量 */
float *pf; /* pf 是一个浮点型指针变量*/
char *pc; /* pc 是一个字符型指针变量*/
char (*sp)[5]; /* sp 是一个字符数组指针变量*/
int **pi; /* pi 是一个指针变量,它是一个指向整型指针的指针变量*/
int (*pf)(); /* pf 是一个函数指针变量,它指向一个函数,该函数返回一个整型值*/
int *(*pf)(); /* pf 是一个函数指针变量,它指向一个函数,该函数返回指向一个整值的指针*/
下面这些不是指针变量:
char *str[5]; /* str 是一个字符串数组,这个数组有5个元素,每个数组元素是指向一个字符串的指针*/
int *pf(); /* pf 是一个函数,这个函数返回指向一个整型值的指针*/
对指针变量的引用,由取地址运算符 “&” 和取值运算符 “*” 来完成。
故名思意 “&” 就是用来得到变量的内存地址。“*” 就是用来得到内存地址里所存储的值。
在指针运算中,取地址运算符 “&” 可用来将变量的地址赋给指针变量。如:
char c='a'; /*定义字符型变量*/
char *cp; /*定义字符型指针*/
cp=&c; /*将变量c的地址赋给指针cp*/
值得注意的是,在为指针赋地址时,指针的类型应该与所指地址的变量数据类型一致。并且取址运算符 “&” 只能用于变量或数组元素,而不能用于表达式或数字常量,如下面用法就是错误的:
int *p,x,a[10];
p=&(x+1);
p=&234;
在对指针赋值后,就可以通过指针来进行对该变量地址的访问了。对指针内容的访问由取值运算符 “*”来执行。
char c; /*定义一个字符变量c*/
char *cp; /*定义一个字符指针变量cp*/
cp=&c; /*给指针cp赋值,即取得字符变量c的内存地址*/
*cp='b'; /*把值存入内存空间。相当于c='b'*/
在使用指针时,应该注意以下事项:
1、在对指针变量进行访问之前,一定要先为其赋地址,否则将发生不可预料的错误。
下面所示的是错误的使用方法:
int *p;
*p=100;
如果执行这段程序,将引起程序崩溃,因为没有对指针 p 赋内存地址,在执行语句 *p=100时,*p指向不可知的内存地址,而对不可知内存地址时行赋值,必将导致程序出错。
2、为指针变量赋值时,还可以用其他的指针或使用NULL来进行。
例如:
int *p,*q;
int n;
p=&n;
q=p;
p=NULL;
上面的程序执行后,指针q将指向整型变量n所在的内存地址,指针p指向空。
3、除NULL外,指针必须指向内存中实际存在的地址,不可以在程序中用非地址表达式给指针变量赋值。
下面的方法是错误的:
int *p,i=100;
p=i+100; /*不能用非地址表达式来为指针赋值*/
p=1000; /*不能用常量为指针赋值*/
*p=999; /*没有对指针变量p赋内存地址*/