7_1 指针的基本概念
_1.1 地址与指针
C语言中通常把地址成为指针。
_1.2 内存单元的指针与内存单元的内容
_1.3 变量的指针
变量的指针就是变量的地址
_1.4 直接访问与间接访问
7_2 指向变量的指针变量
_2.1 指针变量的定义
形式:基类型说明符 *变量名 如:int *p1
“*”也是一个说明符,p1是一个指针变量。
_2.2 指针变量的引用
1. 指针的专用运算符
(1) 取地址运算符& 例:&变量名
(2)指针运算符* 例:*变量名
2.指针变量的赋值
(1)指针变量的初始化
int a;
int *ap=&a; /*定义指向整体变量a的指针变量ap*/
(2) 赋值语句:
①int *ap=&a,a; /*错误,不能把未定义的变量a的地址赋给ap*/
/*不允许把一个数赋予指针变量,被赋值的指针变量前也不能再加“*”说明符。*/
//②错例:
int *p;
p=1000; /*不能把一个数赋予指针变量*/
*p=&a; /*被赋值的指针变量前不能再加“*”说明符*/
(3)将已被赋值的指针变量的值赋给另一指针变量
int a,*ap,*bp;
ap=&a; /*使指针变量ap指向变量a*/
bp=ap; /*将指针变量ap的值赋给指针变量bp;执行该语句后ap和bp都指向同一变量a*/
注:只有相同类型的指针变量之间可以相互赋值。
错例:
int a=3,*ap=&a;
float bp;
bp=ap; /*错误,指针变量bp只能指向float型变量(只能保存float型变量的地址)*/
(4) 可以给指针变量赋0值如:
char *p=0;
该指针称为空指针,为了程序的可读性,通常符号常量NULL来表示空指针的值。如:
char *p=NULL;
3. 指针变量加减一个整数
一个指针加一个整数,表示将指针后移;相反,一个指针减一个整数,表示将指针前移。
4. 两个同类指针变量相减
用于数组,差值表示两个指针变量之间相隔的元素个数
5. 两个同类指针变量作比较运算
用于判断先后关系
6. 指针变量的引用举例
【例7-1】 通过指针变量引用变量的值
#include<stdio.h>
int main()
{
int a,b;
int *ap,*bp;
a=100;
b=10;
ap=&a;
bp=&b;
printf("%d,%d\n",a,b);
printf("%d,%d\n",*ap,*bp);
return 0;
}
【例7-2】 指针变量及其简单运算
#include<stdio.h>
int main()
{
int x=3,y,*xp=&x;
y=*xp+5;
printf("y=%d\n",y);
y=++*xp;
printf("%d\n",y);
y=*xp++;
printf("x=%d,y=%d\n",x,y); /*表示把x的值赋给y再使xp后移,即等价于y=*xp;xp++;*/
return 0;
}
注:“++”和“*”的运算优先级相同且都是自右向左。
_2.2 指针变量作为函数参数
【例7-3】 用一般变量作为参数,不能实现交换。
#include<stdio.h>
int main()
{
int swap(int x,int y);
int a=100,b=10;
printf("%d,%d\n",a,b);
swap(a,b);
printf("%d,%d\n",a,b);
return 0;
}
int swap(int x,int y) /*交换指针变量ap,bp所指向是地址单元中的内存*/
{
int temp;
temp=x;
x=y;
y=temp;
}
【例7-4】若改写为指针函数为参数即可交换。
#include<stdio.h>
int main()
{
int swap(int *ap,int *bp);
int a=100,b=10;
printf("%d,%d\n",a,b);
swap(&a,&b);
printf("%d,%d\n",a,b);
return 0;
}
int swap(int *ap,int *bp) /*交换指针变量ap,bp所指向是地址单元中的内存*/
{
int temp;
temp=*ap;
*ap=*bp;
*bp=temp;
}
7_3指针与数组
_3.1 指针与一维数组
1. 指向数组元素的指针变量
形式:基类型说明符 *指针变量 如:
int a[10];
int *p;
p=&a[0];
C语言规定,把数组的首地址称为数组的指针。
(1)p、a、&a[0]均指向同一单元,它们是数组a的首地址,但是p是指针变量,而a、&a[0]都是指针常量。
2. 通过指针引用数组元素
三种方法:①下标法 ②常量指针法 ③指针变量法。
(1)下标法
#include<stdio.h>
int main()
{
int a[5],i;
printf("Please input 5 numbers:");
for (i=0;i<5;i++)
scanf("%d",&a[i]);
for (i=0;i<5;i++)
printf("a[%d]=%-4d",i,a[i]);
printf("\n");
return 0;
}
(2)常量指针法:
#include<stdio.h>
int main()
{
int a[5],i;
printf("Please input 5 numbers:");
for (i=0;i<5;i++)
scanf("%d",a+i);
for (i=0;i<5;i++)
printf("a[%d]=%-4d",i,*(a+i));
printf("\n");
return 0;
}
(3)指针变量法:
#include<stdio.h>
int main()
{
int a[5],i,*p=a;
printf("Please input 5 numbers:");
for (i=0;i<5;i++)
scanf("%d",p+i);
for (i=0;i<5;i++)
printf("a[%d]=%-4d",i,*(p+i));
printf("\n");
return 0;
}
(4)指针带下标法:
#include<stdio.h>
int main()
{
int a[5],i,*p=a;
printf("Please input 5 numbers:");
for (i=0;i<5;i++)
scanf("%d",&p[i]);
for (i=0;i<5;i++)
printf("a[%d]=%-4d",i,p[i]);
printf("\n");
return 0;
}
(5)逐个移动指针法:
#include<stdio.h>
int main()
{
int a[5],i,*p=a;
printf("Please input 5 numbers:");
for (i=0;i<5;i++)
scanf("%d",p++);
p=a;
for (i=0;i<5;i++)
printf("a[%d]=%-4d",i,*p++);
printf("\n");
return 0;
}
3.用数组的指针作为函数的参数
【例7-7】用冒泡法对10个整数按升序排列
#include<stdio.h>
#define N 5
int main()
{
void output(int *p,int n);
void sort (int x[],int n);
int a[N],i,*p;
printf("请输入%d个整数:\n",N);
for (i=0;i<N;i++)
scanf("%d",&a[i]);
printf("\n");
printf("原数组如下:\n");
output (a,N);
p=a;
sort (p,N);
printf("升序结果如下:\n");
output (a,N);
return 0;
}
void output (int *p,int n)
{ int i;
for(i=0;i<n;i++)
printf("%-4d",*(p+i));
printf("\n");
}
void sort (int x[],int n)
{ int i,j,k,t;
for(i=0;i<n-1;i++)
{
for (j=0;j<n-i-1;j++)
if (x[j]>x[j+1])
{t=x[j];x[j]=x[j+1];x[j+1]=t;}
}
}
_3.2 指针与多维数组
1.多维数组的地址
2.指向二维数组元素的指针变量
【例7-9】用指针变量输入多维数组的值
#include<stdio.h>
int main()
{
int a[2][3]={{1,2,3},{4,5,6}},i;
int *p=a[0];
for (i=0;i<6;i++)
{
printf("%-4d",p[i]);
if ((i+1)%3==0) printf("\n");
}
return 0;
}
3.指向一维数组的指针变量
形式:类型说明符 (*指针变量名)[长度];如:
int (*p)[3];
【例7-10】用指向一维数组的指针变量输出二维数组中的各元素值。
#include<stdio.h>
int main()
{
int a[2][3]={1,2,3,4,5,6};
int *(p)[3];
int i,j;
for (i=0;i<2;i++)
{
for (j=0;j<3;j++)
printf("%-4d",*(*(p+i)+j));
printf("\n");
}
return 0;
}
7_4 字符串与指针
_4.1 字符指针的定义与引用
对指向字符变量的指针变量应赋予该字符变量的地址。如:
char c,*p=&c;
对指向字符串的指针变量应赋予一个字符串的首地址,如:
char c,*p="China";
等效于:char *p; p="China";
【例7-11】用字符指针处理字符数组中的字符串
#include<stdio.h>
int main()
{
char s[]="China";
char *p=s;
while (*p!='\0')
{
putchar(*p);
p++;
}
printf("\n");
return 0;
}
【例7-12】用字符指针处理字符串
#include<stdio.h>
int main()
{
char s[]="China";
char *p=s;
printf("%s\n",p);
return 0;
}
_4.2 字符指针作为函数参数
【例7-14】对字符串内容作修改
#include<stdio.h>
void change (char *s)
{
s[2]='r';
}
int main()
{ char a[]="file";
change (a);
printf("%s\n",a);
return 0;
}
7_5 指针数组
_5.1 用指针数组处理二维数组
【例7-15】 用指针数组处理二维数组
#include<stdio.h>
int main()
{
int a[2][3]={{1,2,3},{4,5,6}},i,j;
int *pa[2]; /*定义数组pa,它的两个数组pa[0]和pa[1]都是存放指针变量的*/
pa[0]=a[0];
pa[1]=a[1];
for (i=0;i<2;i++)
{ for (j=0;j<3;j++)
printf("%-4d",*(pa[i]+j));
printf("\n");
}
return 0;
}
_5.2 用字符指针数组处理一组字符串
【例7-16】 用冒泡法对字符按字母顺序升序排列
#include<stdio.h>
#include<string.h>
void sort (char *a[],int n)
{ int i,j;
char *t;
for (i=0;i<n-1;i++)
for (j=0;j<n-i-1;j++)
if (strcmp (a[j],a[j+1])>0)
{t=a[j];a[j]=a[j+1];a[j+1]=t;}
}
int main()
{ char *p[5]={"Basic","Pascal","Fortran","C","Java"};
int i;
sort (p,5);
for(i=0;i<5;i++)
printf("%s\n",p[i]);
return 0;
}
7_6 指向指针的指针
二级指针的定义格式: 类型说明符 **指针变量名; 如:
int **p;
#include<stdio.h>
int main()
{ char *pa[5]={"Basic","Pascal","Fortran","C","Java"};
char **p;
p=pa;
while (pa<pa+5)
{
printf("%s\n",*p);
p++;
}
return 0;
}
7_7 指针与函数
_7.1 指针型函数
指针型函数:返回指针值的函数
形式:类型说明符 *函数名(形参表列)
{
…… /*函数体*/
}
【例7-18】输入一个1~7之间的函数,输出对应星期名的英语单词。
#include<stdio.h>
char *day_name(int n)
{
char *name[]={"Monday ","Tuseday","Wednesday","Thursday","Friday","Saturday","Sunday"};
return (name[n-1]);
}
int main()
{ int i;
char *day_name(int n);
printf("\t星期名对应的英文单词查询\n请输入一个1~7之间的整数:");
scanf("%d",&i);
while (i<1||i>7)
{
printf("出错!,请重新输入:");
scanf("%d",&i);
}
printf("星期%d对应的英语单词:%s\n",i,day_name(i));
return 0;
}
_7.2 指向函数的指针变量
格式:类型说明符 (*指针变量名)();如:
int (*p)();
【例7-19】 求两数较大者
#include<stdio.h>
int max(int a,int b)
{ if(a>b)
return a;
else return b;
}
int main()
{
int x,y,z;
int (*p)();
p=max;
printf("请输入两个整数(用逗号分隔):\n");
scanf("%d,%d",&x,&y);
z=(*p)(x,y);
printf("两数中较大者为:%d\n",z);
return 0;
}
7_8 指针应用过程中的注意事项
1. 要准确理解指针的含义,区别指针和指针变量的不同含义。
2. 在对数组进行操作时,要能正确的使用指针。
3. 读者须对各种有关的指针变量定义形式加深理解。
4. void指针,即“指向空类型的指针”,是指不指向具体数据对象的指针。
5. 指针还可以实现对动态分配的内存空间进行有效的管理。
C语言中,常用malloc()和free()这两个函数以及sizeof运算符动态分配和释放内存空间。
malloc()函数和free()函数所需的信息通常在头文件stdio.h 中,其函数原型及功能如下:
(1)malloc()函数
函数原型:
void *malloc (unsigned size)
功能:从内存分配一个大小为size个字节的内存空间。如果分配成功,返回新分配内存的首地址;如果没有足够的内存分配,则返回NULL。
为确保内存分配准确,函数malloc()通常和运算符sizeof 一起使用。例:
int *p;
p=(int* )malloc(20*sizeof(int));/*分配20个所需的内存空间*/
(2) free函数
函数原型:void free(void *p);
功能:释放由指针变量p所指向的内存块,无返回值。如:
int *p;
p=(int* )malloc(20*sizeof(int));/*分配20个所需的内存空间*/
……
free(p);
【例7-20】 输入n名学生的C语言成绩,并将这些成绩逆序输出。
#include<stdio.h>
int main()
{
float *score;
int n,i;
printf("请输入学生人数:");
scanf("%d",&n);
score=(float*)malloc(n*sizeof(float));
if(!score)
printf("分配空间失败!\n");
else
{
printf("请输入%d个学生的成绩(空格分隔):\n",n);
for (i=0;i<n;i++)
scanf("%f",score+i);
printf("逆向输出各成绩如下:\n");
for (i=n-1;i>=0;i--)
printf("%7.2f",score[i]);
printf("\n");
free(score);
}
return 0;
}