7_1 指针的基本概念数组
_1.1 地址与指针 函数
C语言中一般把地址成为指针。指针
_1.2 内存单元的指针与内存单元的内容code
_1.3 变量的指针对象
变量的指针就是变量的地址内存
_1.4 直接访问与间接访问字符串
7_2 指向变量的指针变量input
_2.1 指针变量的定义原型
形式:基类型说明符 *变量名 如:int *p1string
“*”也是一个说明符,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; }