首页 第10章 指针

第10章 指针

举报
开通vip

第10章 指针nullnull第十章 主要内容 主要内容 10.1地址和指针的概念 10.2变量的指针和指向变量的 指针变量 10.3数组与指针 10.4字符串与指针 10.5指向函数的指针 10.6返回指针值的函数 10.7指针数组和指向指针的指针 10.8有关指针的数据类型和指针运算的小结10.1 地址和指针的概念10.1 地址和指针的概念内存区的每一个字节有一个编号,这就是“地址” 。如果在程序中定义了一个变量,在对程序进行编译时,系统就会给这个变量分配内存单元。 1.按变量地址存取变量...

第10章  指针
nullnull第十章 主要内容 主要内容 10.1地址和指针的概念 10.2变量的指针和指向变量的 指针变量 10.3数组与指针 10.4字符串与指针 10.5指向 函数 excel方差函数excelsd函数已知函数     2 f x m x mx m      2 1 4 2拉格朗日函数pdf函数公式下载 的指针 10.6返回指针值的函数 10.7指针数组和指向指针的指针 10.8有关指针的数据类型和指针运算的小结10.1 地址和指针的概念10.1 地址和指针的概念内存区的每一个字节有一个编号,这就是“地址” 。如果在程序中定义了一个变量,在对程序进行编译时,系统就会给这个变量分配内存单元。 1.按变量地址存取变量值的方式称为“直接访问”方式 printf(″%d″,i); scanf(″%d″,&i); k=i+j; nullnull2. 另一种存取变量值的方式称为“间接访问”的方式。即,将变量i的地址存放在另一个变量中。在C语言中,指针是一种特殊的变量,它是存放地址的。null一个变量的地址称为该变量的“指针”。 例如,地址2000是变量i的指针。如果有一个变量专门用来存放另一变量的地址(即指针),则它称为“指针变量”。上述的i_pointer就是一个指针变量。指针和指针变量的定义:10.2 变量的指针和指向变量的指针变量10.2 变量的指针和指向变量的指针变量10.2.1 定义一个指针变量定义指针变量的一般形式为 基类型 *指针变量名; null下面都是合法的定义: float *pointer_3; char *pointer_4; 可以用赋值语句使一个指针变量得到另一个变 量的地址,从而使它指向一个该变量。 例如: Pointer_1=&i; Pointer_2=&j;null在定义指针变量时要注意两点:null10.2.2 指针变量的引用 注意:指针变量中只能存放地址(指针), 不要将一个整数(或任何其他非地址类型的数据) 赋给一个指针变量。 例10.1 通过指针变量访问整型变量#include void main ( ) { int a,b; int*pointer_1, *pointer_2; a=100;b=10; pointer_1=&a; /*把变量a的地址赋给 pointer_1 */ nullpointer_2=&b; /*把变量b的地址赋给pointer_2 */ printf(″%d,%d\n″,a,b); printf(″%d,%d\n″,*pointer_1, *pointer_2); }null对“&”和“*”运算符说明: 如果已执行了语句 pointer_1=&a; (1)&* pointer_1的含义是什么? “&”和“*”两个运算符的优先级别相同,但按自右而左方向结合。因此,&* pointer_1与&a相同,即变量a的地址。 如果有pointer_2 =&* pointer_1 ;它的作用是将&a(a的地址)赋给pointer_2 ,如果pointer_2原来指向b,经过重新赋值后它已不再指向b了,而指向了a。nullnull(2) *&a的含义是什么? 先进行&a运算,得a的地址,再进行*运算。*&a和*pointer_1的作用是一样的,它们都等价于变量a。即*&a与a等价。(3) (*pointer_1)++相当于a++。null例10 . 2 输入a和b两个整数,按先大后小的顺序输出 a和b。#include void main() { int *p1,*p2,*p,a,b;   scanf(″%d,%d″,&a,&b);  p1=&a;p2=&b;   if(a<b)  {p=p1;p1=p2;p2=p;}  printf(″a=%d,b=%d\n\n″,a,b); printf(″max=%d, min=%d\n″,*p1,*p2); } null运行情况如下: 5,9↙ a=5,b=9 max=9,min=5 当输入a=5,b=9时,由于a<b,将p1和p2交换。交换前的情况见图(a),交换后见图(b)。nullnull10.2.3 指针变量作为函数参数例10 . 3 对输入的两个整数按大小顺序输出 #include void main() {void swap(int *p1,int *p2) ;  int a,b;  int *pt1,*pt2; scanf(″%d%d″,&a, &b) ;  pt1=&a; pt2=&b ;   if (a 方法 快递客服问题件处理详细方法山木方法pdf计算方法pdf华与华方法下载八字理论方法下载 ,与以前介绍的指向变量的指针变量相同。 例如:int a[10]; (定义a为包含10个整型数据的数组) int*p; (定义p为指向整型变量的指针变量) 应当注意,如果数组为int型,则指针变量的基类型亦应为int型。 10.3.1 指向数组元素的指针null对该指针变量赋值: p=&a[0]; 把a[0]元素的地址赋给指针变量p。也就是使p指向a数组的第0号元素,如图:null10.3.2通过指针引用数组元素引用一个数组元素,可以用:   (1) 下标法,如a[i]形式;   (2) 指针法,如*(a+i)或*(p+i)。其中a是数组名,p是指向数组元素的指针变量,其初值p=a。例10.5 输出数组中的全部元素。 假设有一个整型数组a,有10个元素。要输出各元素的值有三种方法: null(1)下标法。 #include void main() { int a[10];   int i;  for(i=0;i<10;i++)   scanf(″%d″,&a[i]);   printf(″\n″);  for(i=0;i<10;i++)   printf(″%d″,a[i]); }null(2) 通过数组名计算数组元素地址,找出元素的值。 #include void main() { int a[10];   int i;  for(i=0;i<10;i++ )   scanf(″%d″,&a[i]);   printf(″\n″);   for(i=0;i<10;i++)    printf(″%d″,*(a+i) );   }null(3) 用指针变量指向数组元素。 #include void main() { int a[10];   int *p,i;   for(i=0;i<10;i++)     scanf(″%d″,&a[i]);   printf(″\n″);   for(p=a;p<(a+10);p++)    printf(″%d ″,*p); }null10.3.3 用数组名作函数参数在第8章8.7节中介绍过可以用数组名作函数的参数 如: void main() {if(int arr[],int n); int array[10]; ┇ f (array,10); ┇ } void f(int arr[ ],int n) { ┇ }null如果有一个实参数组,想在函数中改变此数组中的元素的值,实参与形参的对应关系有以下4种情况: (1) 形参和实参都用数组名,如: void main() void f (int x[ ],int n) { int a[10]; { … … f (a,10); } } nullnull(2) 实参用数组名,形参用指针变量。如: void main() void f (int *x,int n) {int a[10]; { … … f (a,10); } }(3)实参形参都用指针变量。例如: void main() void f (int *x,int n) {int a[10], *p=a; { ┇ ┇ f (p,10); } } nullnull(4) 实参为指针变量,形参为数组名。如: void main() void f (int x[ ],int n) {int a[10],*p=a; { ┇ ┇ f (p,10); } } null例10.9 用选择法对10个整数按由大到小顺序排序。 #include void main() { void sort(int x[ ],int n); int*p,i,a[10]; p=a; for(i=0;i<10;i++)    scanf(″%d″,p++); p=a; sort(p,10); for(p=a,i=0;i<10;i++) {printf (″%d″,*p);p++;} }nullvoid sort(int x[ ],int n) { int i,j,k,t; for(i=0;i<n-1;i++)  {k=i;   for(j=i+1;j<n;j++)   if(x[j]>x[k])  k=j;   if(k!=i)   {t=x[i]; x[i]=x[k]; x[k]=t;}   } }null 一维数组名a就是数组元素a[0]的地址,因此*a就等价于a[0]。 若int *p=a; 则p++将指向下一个元素。a++是错误的,原因:数组名是常数。 *p++ 先是指针的间接引用,然后将指针自加; *++p 先将指针自加,然后是指针的间接引用; ++*p 先将指针指向的变量自增,且指针不变,然后使用该变量; (*p)++ 先使用指针指向的变量,且指针不变,然后将该变量自增。注意:指针与++连用时的情况nullmain( ) { int a[10]={10,20,30,40,50,60,70,80,90,100}; int *p=a; printf("%d %d\n" ,*++p, *p++ ); }运行结果为: 30 10main( ) { int a[10]={10,20,30,40,50,60,70,80,90,100}; int *p=a; printf("%d %d\n" ,++*p2, (*p2)++); }运行结果为: 12 10null10.3.4 多维数组与指针 用指针变量可以指向一维数组中的元素,也可以指向多维数组中的元素。但在概念上和使用上,多维数组的指针比一维数组的指针要复杂一些。 1. 多维数组元素的地址先回顾一下多维数组的性质,可以认为二维数组是“数组的数组”,例 : 定义int a[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}}; 则二维数组a是由3个一维数组所组成的。设二维数组的首行的首地址为2000,则nullnull2 . 指向多维数组元素的指针变量(1) 指向数组元素的指针变量例10.11 用指针变量输出二维数组元素的值 #include void main() { int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};   int*p;   for(p=a[0];p<a[0]+12;p++) { if ((p-a[0])%4==0)printf(″\n″);   printf(″%4d″,*p); } }  运行结果如下: 1 3 5 7 9 11 13 15 19 21 23 null (2) 指向由m个元素组成的一维数组的指针变量 int b[3][4];则b[0]是第0行的一维数组的数组名;b[1]是第1行的一维数组的数组名;b[2]是第2行的一维数组的数组名; 而数组名b是由以上三个一维数组名b[0]、b[1]、b[2]构成的一维数组的数组名,从而b为元素b[0]的地址,而b不是b[0][0]的地址。 因此 int *p=b; 是错误的; 若int *p; 则p=b[0]; 或p=b[1]; 或p=b[2]; 都有是正确的。null 从而引入了指向一维数组的指针变量: int b[3][4]; int (*p)[4]; p=b; 数组元素b[i][j]可以采用以下六种形式 关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf 示: b[i][j] *(b[i]+j) *(*(b+i)+j) p[i][j] *(p[i]+j) *(*(p+i)+j)nullmain( ) { int a[2][3]={1,2,3,4,5,6}; int (*p)[3]; p=a; for(int i=0; i<2; i++) { for(int j=0; j<3; j++) printf("%6d", *(*(p+i)+j) ); printf("\n"); } }null例10.13 出二维数组任一行任一列元素的值#include void main ( ) { int a[3][4]={1,3,5,7,9,11, 13,15,17,19,21,23};  int (*p)[4],i,j; p=a;  printf(″Enter i、j:\n″) ; scanf(″%d%d″,&i,&j) ; printf(″a[%d, %d]=%d\n″, i, j, *(*(p+i)+j)); } 运行情况如下: i=1,j=2↙(本行为键盘输入) a[1,2]=13null3. 用指向数组的指针作函数参数例10.13 有一个班,3个学生,各学4门课,计算总平均分数以及第n个学生的成绩。 这个 快递公司问题件快递公司问题件货款处理关于圆的周长面积重点题型关于解方程组的题及答案关于南海问题 目只是为了说明用指向数组的指针作函数参数而举的例子。用函数average求总平均成绩,用函数search找出并输出第i个学生的成绩。null#include void main() { void average(float *p,int n); void search(float (*p)[4],int n); float score[3][4]={{65,67,70,60},{80, 87,90,81},{90,99,100,98}}; average(*score,12);/*求12个分数的平均分*/ search(score,2);/*求序号为2的学生的成绩*/ }nullvoid average(float *p,int n) { float *p-end ; float sum=0, aver; p_end=p+n-1; for( ;p<=p-end ;p++) sum=sum+(*p); aver=sum/n; printf(″average=%5.2f\n″,aver); }nullvoid search(float (*p)[4],int n) / * p是指向具有4个元素的一维数组的指针 */{int i; printf(″the score of No. %d are:\n″,n); for(i=0;i<4;i++) printf(″%5.2f″,*(*(p+n)+i) ); }程序运行结果如下: average=82.25 The score of No.2 are: 90.00 99.00 100.00 98.00null10.7.1 指针数组的概念若数组元素是某种类型的指针,这样的数组称为指针数组。 int b[3][4]; int *p [3]; p[0]=a[0]; p[1]=a[1]; p[2]=a[2]; 数组元素b[i][j]也可以采用指针来表示: p[i][j] *(p[i]+j) *(*(p+i)+j)nullmain( ) { int a[2][3]={10,20,30,40,50,60}; int *p[2]; p[0]=a[0]; p[1]=a[1]; for(int i=0; i<2; i++) { for(int j=0; j<3; j++) printf("%6d", *(*(p+i)+j) ); printf("\n"); } }10.4 字符串与指针10.4 字符串与指针10.4.1字符串的表示形式 例 10.15 定义一个字符数组,对它初始化, 然后输出该字符串 #include void main() {char string[ ]=″I love China!″; printf(″%s\n″,string); } (1) 用字符数组存放一个字符串,然后输出该字符串。null(2) 用字符指针指向一个字符串。 可以不定义字符数组,而定义一个字符指针。用字符指针指向字符串中的字符。 例10.16 定义字符指针 #include void main() {char*string=″ I love China!″;  printf(″%s\n″,string); }null例10.17 将字符串a复制为字符串b。 #include void main() {char a[ ]=″I am a boy.″,b[20]; int i; for(i=0;*(a+i)!=′\0′;i++)   *(b+i)=*(a+i); *(b+i)=′\0′; printf(″string a is :%s\n″,a); printf(″string b is:″); for(i=0;b[i]!=′\0′;i++)   printf(″%c″,b[i]); printf(″\n″); }null 也可以设指针变量,用它的值的改变来指向字符串中的不同的字符。 例10.18 用指针变量来处理例10.17问题。#include void main() {char a[ ] =″I am a boy. ″,b[20],*p1,*p2; int i;   p1=a;p2=b; for(;*p1!=′\0′;p1++,p2++) *p2=*p1; *p2=′\0′;null printf(″string a is:%s\n″,a); printf(″string b is:″); for(i=0;b[i]!=′\0′;i++) printf(″%c″,b[i]); printf(″\n″); }程序必须保证使p1和p2同步移动 nullnull10.4.2 字符指针作函数参数例10.19 用函数调用实现字符串的复制 #include void main() { void copy_string(char from[ ], char to[ ]); char a[ ]=″I am a teacher.″; char b[ ]=″you are a student.″; printf(“string a=%s\n string b=%s\n″, a,b); printf(“copy string a to string b:\n ”); copy_string (a,b); printf("\nstring a=%s\nstring b=%s\n",a,b);   }(1) 用字符数组作参数nullvoid copy_string(char from[ ], char to[ ]) { int i=0; while(from[i]!=‘\0’)   {to[i]=from[i];i++;}  to[i]= ‘\0’ ; } 程序运行结果如下: string a=I am a teacher. string b =you are a student. copy string a to string b: string a =I am a teacher. stringb=I am a teacher.null(2) 形参用字符指针变量 #include void main() { void copy_string(char * from, char *to); char *a=″I am a teacher .″; char *b=″you are a student .″; printf(“string a=%s\nstring b=%s\n″,a,b); printf("copy string a to string b:\n "); copy_string (a,b); printf("\nstring a=%s\nstring b=%s\n",a,b);   }nullvoid copy_string(char *from,char *to) { for(;*from!=‘\0’;from++,to++)    *to=*from;   *to= ‘\0’ ; }(3) 对copy string 函数还可作简化 1、将copy_string函数改写为 void copy_string (char *from,char *to) { while((*to=*from)!=‘\0’) {to++;from++;}   *to= ‘\0’ ; }null• copy_string函数的函数体还可改为 { while((*to++=*from++)!= ‘\0’ ); }•copy_string函数的函数体还可写成 { while(*from!= ‘\0’ )    *to++=*from++;  *to=′\0′; }null•上面的while语句还可以进一步简化为下面的while语句: while(*to++=*from++); 它与下面语句等价: while((*to++=*from++)!=′\0′); 将*from赋给*to,如果赋值后的*to值等于′\0′则循环终止(′\0′已赋给*to) •函数体中while语句也可以改用for语句: for(;(*to++=*from++)!=0;); 或 for(;*to++=*from++;);null•也可用指针变量,函数copy_string可写为 void copy_string (char from[ ],char to[ ]) {char*p1,*p2; p1=from;p2=to;  while((*p2++=*p1++)!=′\0′); }null(1) 字符数组由若干个元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址(字符串第1个字符的地址),决不是将字符串放到字符指针变量中。 (2)赋值方式。对字符数组只能对各个元素赋值,不 能用以下办法对字符数组赋值。 char str[14]; str=″I love China!″; 而对字符指针变量,可以采用下面方法赋值: char*a; a=″I love China!″; 10.4.3 对使用字符指针变量和字符数组的讨论字符数组和字符指针变量二者之间的区别:null(3)对字符指针变量赋初值: char *a=″I love China!″;等价于 char*a; a=″I love Chian!″; 而对数组的初始化: char str[14]={″I love China!″}; 不能等价于 char str[14]; str[]=″I love China!″;null(4) 定义了一个字符数组,在编译时为它分配内存单元,它有确定的地址。而定义一个字符指针变量时,给指针变量分配内存单元,在其中可以放一个字符变量的地址。 例如: char str[10];   scanf(″%s″,str);null(5) 指针变量的值是可以改变的,例如:例10.20 改变指针变量的值#include void main( ) {char*a=″I love China!″; a=a+7; printf(″%s″,a); }null#include void main() {char*a=″I love China!″; int i; printf ( “ The sixth character is %c\n",a[5]); for(i=0;a[i]!=‘\0’;i++) printf(″%c″,a[i]); } 若定义了一个指针变量,并使它指向一个字符串,就可以用下标形式引用指针变量所指的字符串中的字符。例如: null10.5 指向函数的指针10.5.1 用函数指针变量调用函数用指针变量可以指向一个函数。 函数在编译时被分配给一个入口地址。这个函数的入口地址就称为函数的指针。 null#include void main() { int max(int,int);   int a,b,c;  scanf(″%d,%d″,&a,&b); c=max(a,b);  printf(″a=%d,b=%d,max=%d ″,a,b,c); } int max(int x,int y) { int z; if(x>y)z=x;   else z=y; return(z); }null将 main 函数改写为 #include void main() { int max(int,int); int (*p)( ); int a,b,c; p=max;   scanf(″%d,%d″,&a,&b); c=(*p)(a,b);   printf(“a=%d,b=%d,max=%d”,a,b,c); }null10.5.2 用指向函数的指针作函数参数 函数指针变量常用的用途之一是把指针作为参数传递到其他函数。指向函数的指针也可以作为参数,以实现函数地址的传递,这样就能够在被调用的函数中使用实参函数。null 实参函数名 f1    f2      ↓ ↓ void sub(int (*x1)(int),int (*x2)(int,int)) { int a,b,i,j; a=(*x1)(i); /*调用f1函数*/ b=(*x2)(i,j);/*调用f2函数*/ … }null10.6 返回指针值的函数一个函数可以带回一个整型值、字符值、实型值等,也可以带回指针型的数据,即地址。其概念与以前类似,只是带回的值的类型是指针类型而已。 这种带回指针值的函数,一般定义形式为 类型名 *函数名(参数表列); 例如: int *a(int x,int y);null例10.24 有若干个学生的成绩(每个学生有4门课程),要求在用户输入学生序号以后,能输出该学生的全部成绩。用指针函数来实现。 #include void main() {float *score[ ][4]={{60,70,80,90}, {56,89,67,88},{34,78,90,66}}; float*search(float (*p)[4],int n); float*pm; int i,m; printf(″enter the number of student:″); scanf(″%d″,&m); printf(″The scores of No.%d are:\n″,m); null pm=search(score,m);  for(i=0;i<4;i++)  printf(″%5.2f \t″,*(pm+i)); } float * search(float (*p)[4],int n) { float *pt; pt=*(p+n); return(pt); } 运行情况如下: enter the number of student:1↙ The scores of No. 1 are: 56.00 89.00 67.00 88.00null10.7 指针数组和指向指针的指针10.7.1 指针数组的概念一个数组,若其元素均为指针类型数据,称为指针数组,也就是说,指针数组中的每一个元素都相当于一个指针变量。 一维指针数组的定义形式为: 类型名数组名[数组长度]; 例如: int*p[4]; char s[5][20], *name[5]; nullnull例10.26 将若干字符串按字母顺序(由小到大)输出。#include #include void main() {void sort(char *name[ ],int n); void printf(char *name[ ],int n);   char *name[ ]={"Follow me","BASIC","Great Wall″,"FORTRAN","Computer design"};   int n=5;  sort(name,n); print(name,n); }nullvoid sort(char *name[ ],int n) {char *temp; int i,j,k; for(i=0;i<n-1;i++)  {k=i;   for(j=i+1;j<n;j++)  if(strcmp(name[k],name[j])>0)k=j;   if(k!=i)  temp=name[i]; name[i]=name[k]; name[k]=temp;}   } } nullvoid print(char *name[ ],int n) { int i;  for(i=0;i<n;i++)    printf(″%s\n″,name[i]); }运行结果为: BASIC Computer design FORTRAN Follow me Great Wallnull10.7.2 指向指针的指针定义一个指向指针数据的指针变量: char**p; p的前面有两个*号。*运算符的结合性是从右到左,因此**p相当于*(*p),显然*p是指针变量的定义形式。如果没有最前面的*,那就是定义了一个指向字符数据的指针变量。现在它前面又有一个*号,表示指针变量p是指向一个字符指针变量的。*p就是p所指向的另一个指针变量。null例10.27 使用指向指针的指针。 #include void main() {char *name[]={"Follow me","BASIC","Great Wall″,"FORTRAN","Computer design"}; char **p; int i; for(i=0;i<5;i++)  {p=name+i;    printf(″%s\n″,*p); } }null指针的指针作函数的参数void swap( int **a, int **b); main( ) { int x=5, y=10; int *p1=&x, *p2=&y; printf(“x=%d, y=%d\n” ,x, y ); swap(&p1, &p2); printf(“x=%d, y=%d\n” ,x, y ); printf(“x=%d, y=%d\n” ,*p1, *p2 ); }null注意:指针p1、p2的指向发生了变化;而变量x、y的值并没有变化。void swap( int **a, int **b ) { int *t; t=*a; *a=*b; *b=t; }null10.7.3 指针数组作main函数的形参  指针数组的一个重要应用是作为main函数的形参。在以往的程序中,main函数的第一行一般写成以下形式:void main()括弧中是空的。   main函数可以有参数,例如: void main(int argc,char *argv[ ])。   命令行的一般形式为: 命令名 参数1 参数2……参数nnull例如一个名为file1.c的文件,它包含以下的main函数:void main(int argc,char *argv[ ]) {while(argc>1) {++argv;   printf(″%s\n″,argv); --argc; } }在DOS命令状态下输入的命令行为 file1 China Beijing 则执行以上命令行将会输出以下信息: China Beijing
本文档为【第10章 指针】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_976306
暂无简介~
格式:ppt
大小:710KB
软件:PowerPoint
页数:0
分类:其他高等教育
上传时间:2012-03-27
浏览量:11