指针,C语言指针完全攻略_1
内存与地址
int main(void)
{
char c='A';
int a=100;
printf("a=%d\n",a);//输出变量a的值
printf("&a=%x\n",&a);//输出变量a的地址
printf("c=%c\n",c);
printf("&c=%x\n",&c);
return 0;
}
程序某次的运行结果为:
指针变量的定义
类型 * 变量名;
例如:
int *pa;
int *pa,*pb;
表示定义了两个指针变量 pa、pb。而:
int *pa,pb;
则仅有 pa 是指针变量,而 pb 是整型变量。
int *pi,a,b; //等价于inta,b,*pi;
表示定义了一个整型指针变量 pi 和两个整型变量 a 和 b。
2) 在使用已定义好的指针变量时,在变量名前面不能加 *。例如:
int *p,a;
*p=&a; //错误,指针变量是p而不是*p
而如下语句是正确的。
int a,*p=&a; //正确
int a,b,*pa,*pb;
char *pc,c;
则:
pa=&a;//正确。pa基类型为int,a为int型变量,类型一致
pb=&c;//错误。pb基类型为int,c为char型变量,类型不一致
pc=&c;//正确。pc基类型为char,c为char型变量,类型一致
*pa=&a;//错误。指针变量是pa而非*pa
4) 变量名是一合法标识符,为与普通变量相区分,一般指针变量名以字母 p(pointer)开头,如 pa、pb 等。
5) 由于是变量,故指针变量的值可以改变,也即可以改变指针变量的指向。
char c1,*pc,c2;//定义了字符变量c1、c2和字符指针变量pc
则如下对指针变量的赋值语句均是正确的。
pc=&c1; //pc指向c1
pc=&c2; //pc不再指向c1,而指向c2
6) 同类型的指针变量可以相互赋值。
int a,*p1,*p2,b;//定义了两个整型变量a,b;两个整型指针变量为p1,p2
float *pf;
以下赋值语句均是正确的。
p2=p1; //p2也指向a,即p1和p2均指向a
pf=p1;//错误。p1,pf虽然都是指针变量,但类型不同,不能赋值
pf=&b; //错误。指针变量pf的基类型为float,b类型为int,不相同
图 2 指针指向变量
指针变量的引用
p=&a;
printf("a=%d\n",a); //通过名字,直接访问变量a空间(读取)
*p=6;//等价于a=6;间接访问a对应空间(存)
“野”指针
本节中,把没有合法指向的指针称为“野”指针。因为“野”指针随机指向一块空间,该空间中存储的可能是其他程序的数据甚至是系统数据,故不能对“野”指针所指向的空间进行存取操作,否则轻者会引起程序崩溃,严重的可能导致整个系统崩溃。
例如:
int *pi,a; //pi未初始化,无合法指向,为“野”指针
*pi=3; //运行时错误!不能对”野”指针指向的空间做存入操作。该语句试图把 3 存入“野”指针pi所指的随机空间中,会产生运行时错误。
a=*pi; //运行时错误!不能对”野”指针指向的空间取操作。该语句试图从“野”指针pi所指的空间中取出数据,然后赋给变量a同样会产生运行时错误。
正确的使用方法:
pi=&a;//让pi有合法的指向,pi指向a变量对应的空间
*pi=3;//把3间接存入pi所指向的变量a对应的空间
指针与数组
一维教组和指针
在 C 语言中,指针变量加 1 表示跳过该指针变量对应的基类型所占字节数大小的空间。指向数组元素的指针,其基类型为数组元素类型,指针加 1 表示跳过一个数组元素空间,指向下一个数组元素。
例如:
int *p,a[10];
p=a; //相当于 p=&a[0];
for (p=a;p<a+N;p++) //用p的移动范围控制循环次数
printf ("%d\t",*p);
int *p,a[10],i;
p=a;
int main (void)
{
int *p,a[N],i;
p=a; //p初始指向a[0]
printf("Input the array:\n");
for(i=0;i<N;i++) //用整型变量i控制循环次数
scanf ("%d",p++); //指针P表示地址,不能写成&P
printf ("the array is :\n");
for(p=a;p<a+N;p++) //用p的移动范围控制循环次数
printf("%d\t", *p);
return 0;
}
补充说明:
输入输出循环控制方法有多种,不管采用哪种,必须准确确定起点和终点的表达式。
1) 输入若采用p的移动范围确定循环次数,则代码如下。
for(p=a;p<a+N;p++)
scanf("%d",p);
这时,for 语句之前的 p=a; 语句可以去掉。
2) 输出若采用移动指针变量 p 控制循环的执行,因为执行完输入操作后,p 已不再指向数组首元素,而是越界的 a[N] 初始位置,故必须重新给 p 赋值,让其指向数组的首元素, 代码如下。
p=a; //重新赋值,让p指向数组首元素
for(i=0;i<N;i++)
printf ("%d\t",*p++);