⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ex6.cpp

📁 C/C++程序设计教程
💻 CPP
📖 第 1 页 / 共 2 页
字号:
             
             ///第6章指针与数组


//	[例6.1]指针作为函数的形参,指针形参可改变其指向的实参变量。
	#include <stdio.h>               //注意&符号在不同位置的作用
    typedef long type,*ptype;          //声明type是long的别名, ptype是long*的别名
    void f(type* x,ptype y){*x+=1;*y+=2;} //x,y是long*型的指针形参     
    void main()       //f函数对间接变量*x,*y 分别执行加1和加2的运算
    {   long a=1,*pa=&a;  	     // 定义a为long型变量,  pa为long*型指针,指向a。
        type b=2,&rb=b;            //定义b为long型变量,声明rb为b的引用
		long*& qa=pa;              //声明引用qa为指针pa的别名
		ptype   pb(&b),&qb=pb;    //定义指针pb初始化&b, 声明引用qb为指针pb的别名
    	printf("%d,%d\t",*pa,*pb);    //*pa,*pb分别是a,b的间接变量		
        f(pa,qb);                   //函数调用f(pa,qb);相当于*pa+=1;    *pb+=2;
        *qa+=1;   rb+=2;    f(&a,&b); //虚实结合导致x=&a,y=&b
        printf("%d,%d\t",a,b);  //对引用rb,qa,qb的操作是对相关左值b,pa,pb的等价操作
	}					//输出:1,2   4,8
// [例6.2]指针自增运算访问数组元素
	  # include<stdio.h>     //if(e) s;格式中的条件表达式e首先完成求值计算和副作用
	void main(void)       //本例题中if所属的语句为空语句,if(e) ; 相当于e;
	 {  int a[ ]={1,2,3,4};   // if(r=p++);相当于 r=p++;等,基本上不用if(e) ;格式
	   int  y,  z,*r,  *p=a;  
       if(r=p++);       /*r=&a[0],  p=&a[1]*/   printf("r=%p,a=%p,p=%p\n",r,a,p);
 	   y=*p++;      /*y=a[1],  p=&a[2]*/    printf("a[0]=%d,a[1]=%d,%p\t",*r,y,p);
	   if(z=(*p)++);   /*z=a[2],  a[2]+=1;*/    printf("a[2]=%d,a[2]=%d,%p\t",z,a[2],p);
	   *p++=*r++;   /*a[2]=a[1];p=&a[3]*/   printf("a[2]=%d,a[3]=%d,%p\n",a[2],*p,p);
    }
//   [例6.3]数组形参的大小形同虚设,p是指针变量,而a表示数组首元素的右值地址
   #include<stdio.h>
    void  f(double p[8]){ printf("sizeof(p)=%d;",sizeof(p)); p++; 	}
    void main (void)       //输出:sizeof(p)=4; sizeof(a)=64
    {  double a[8];  f(a);   printf("sizeof(a)=%d\n",sizeof(a));	}
//    [例6.4] 求内存空间连续n个元素的和
	#include<stdio.h>
    long sum(long x[],int n);//函数原型为一维数组形参,n动态界定寻址内存空间的大小
    long sum(long  [8],int);//函数原型中的8不起作用
	void main()                      // sum(a,n) 求区间{1,2,3,4}的和10
	{   long   a[]={1,2,3,4};         // sum(q,n-1)求区间{2,3,4}的和9
        const int n=sizeof(a)/ sizeof(*a);  // sum(&a[2],n-2) 求区间{3,4}的和7
		long *q=&a[1];               //函数调用sum(a,n+1),sum(q,n)导致越界
		printf("[%d%,%d,%d]\n", sum(a,n),sum(q,n-1),sum(&a[2],n-2));
	}   //输出:[10,9,7]
    long sum(long *p,int n)           //函数定义为一级指针形参
	{   	long s=0 ;                  //p++指向long型数组的下一个元素
		for(int i=0;i<n;p++,i++) s+=*p;//*p得到该位置元素的值
		return s;                    //s+=*p累积地加上这个元素
	}	                          //sum返回以入口指针定位的其后n个元素的和
//	[例6.5]将数组 反序排放为存放
   #include<stdio.h>  
   void swap(long s[],int n,int i)  { long t=s[i];s[i]=s[n-1-i];s[n-1-i]=t;}//s为数组形参
   void inverse(long p[],long *e) 	//p为数组形参,e为指针形参。
   {    for(; p<e;p++,--e )      //访问指针形式将数组逆序存放,p<e是指针的关系比较
	     { long t=*p;*p=*e;*e=t;} //循环体swap(p,e)依次交换间接变量的值
   }    //标题头void inverse(long p[],long *e)可以等价写为void inverse(long *p,long e[])
   void main()                    //数组形参与指针形参是等价的
	{	long s[]={1,2,3,4,5,6,7,8,9};
	    const int n=sizeof(s)/sizeof(s[0]);
	    int i ;for( i=0;i< n/2;i++)    //下标寻址方式将数组逆序存放
		       swap(s, n,i);     // swap(s, n,i);相当于{ long t=s[i];s[i]=s[n-1-i];s[n-1-i]=t;}
	    for( i=0;i<n;i++) printf("%d,",s[i]);  //下标法显示数组元素的值 
	    inverse(s,&s[n-1]);//在调用点inverse函数形参p,e获得初始值p=&s[0],e=s+n-1。
		long *p=&s[0];
        for(i=0;i<n;i++,p++)  printf("%d;",*p); //访问指针形式显示数组元素的值  
	}			//输出结果:9,8,7,6,5,4,3,2,1,1;2;3;4;5;6;7;8;9;

//[例6.6]固定指针和只读指针(固定指针和只读指针都可指向普通(非只读)的数组)
	void intcpy(int *p,const int*q,int n)   //只读指针形参q表示*q在函数体中为右值。     
		{ for(int k=0;k<n; p++,q++,k++) *p=*q; }//左边的函数体与下面程序块等价
	# include<iostream.h>            // { int k=0; while(k<n){*p=*q; p++;q++;k++; } }
     const  int  c[5]={1,2,3,4,5}; //定义只读全局数组,每一个数组元素c[k]为右值
	void main(void)                // c+1,&c[0]等是const int*型的表达式
    {   int a[10];                  //a+1,&a[0]等是int*型的表达式
        int * const  s=a;            //定义固定指针s,初始化为数组名a
        const  int  *r=c;            //定义只读指针r,初始化指向只读数组
        int  k=0;
       for (;k<5;k++,r++) //循环将数组c的5个元素拷贝给数组a的相应元素
	      s[k]=*r; // r++表示只读指针r向后遍历,*r表示读取当前所指位置的内容
		intcpy(a+5,a,5);             //将数组a的前5个元素分别拷贝到后5个元素
        for (k=0;k<10;k++)        cout<<"-"<<a[k];
    }       //输出结果:  -1-2-3-4-5-1-2-3-4-5
//[例6.7]指针的强制类型转换攻击只读数据区    // swap函数实现指针的固定寻址
   #include <stdio.h>                        //固定指针形参s交换数组相邻元素的值
   void swap(int*const s){int t=*s;*s=s[1];s[1]=t;}//s本身不变,间接变量变动
    void main()               /*  int*型的实参可匹配int*const型的形参,反之亦然*/
    {   const	int a[2]={1,2};    printf("%d,%d;",a[0],*(a+1));
	    int* p=(int*)(a+1);          // const int*型地址a+1强制地映射给int*型指针p
		printf("%d,%d-",p[-1]=3,*p=4);// p[-1]=3相当于a[0]=3
		swap((int*)&a[0]); //(int*)&a[0]表示cons  int*型的地址&a[0]转换int*型的地址
		printf("%d,%d",*a,a[1]);      //输出:1,2;3,4-4,3
	}                        /*本质上int*型的右值地址严格地具有int*const型属性*/
//[例6.8] 从二维数组中查找第一个出现的负数
	# include<iostream.h> 
    void main()
    {   const int n=3,m=2;
		int  d[n][m];//定义二维数组
        cout<<"input "<<n*m<<" integers:";
        int j; int i;
        for(i=0;i<n;i++)   for(j=0;j<m;j++)    cin>>d[i][j];
        for(i=0;i<n;i++)
           for(j=0;j<m;j++)      /*if(d[i][j]<0) 等价于if(*(*(d+i)+j)<0) */
                if(*(*(d+i)+j)<0)          goto   found;
        cout<<"not found!"<<endl;         goto   end;
    found:cout<<"d["<<i<<"]["<<j<<"]="<< d[i][j]<<endl;
    end:;
    }
	
//	[例6.9]同一个地址对应不同类型的地址属性
    #include <stdio.h>	
    void main()
    {	 int  b[3][2][2];      //int  (*p)[2][2]=b;int (*q)[2]=b[0];int * r=b[0][0];
		 printf("%p,%p,%p\t",b,b[0],b[0][0]);
	}   //输出:0066FDC8, 0066FDC8, 0066FDC8
//[例6.10]指向二维数组的指针与二维数组
    # include<iostream.h>
    void f(float (*q)[4],int m)              //q是float (*)[4]型数组指针形参
	{   for (int k=0;k<m;k++)              // q[k] 是float*的右值地址
	    { float*   p=q[k];                 //定义指针p,初始化为p=q[k]
  	      for( int j=0;j<4;j++)   	        //通过指针简化了重复的寻址计算
           cout<<p[j]<<"," ;               // p[j]= q[k][j]
  	    } //标题头 void f(float (*q)[4],int m) 可以等价地改为void f(float q[][4],int m)
	}     // float q[][4]为二维数组形参,它等价于数组指针形参float (*q)[4]
 	void main(void)                   //函数调用f(d,M+1), f(d+1,M)导致越界
	{   float d[ ][4]={0,1,2,3,4,5,6,7};    //定义浮点型二维数组d[2][4]
		int const M=sizeof(d)/sizeof(*d);  //d,d+1具有类型属性float (*)[4]
	    f(d,M); //实参d 初始化指针形参q,f(d,M)访问内存区间{0,1,2,3,4,5,6,7}
	    f(d+1,M-1);// d+1初始化指针形参q,f(d+1,M-1)访问内存区间{4,5,6,7}
    }                               //输出:0,1,2,3,4,5,6,7, 4,5,6,7,
 //  [例6.11]数组指针形参或二维数组形参实现求数组空间的和
	#include<stdio.h>  
	double   sum(double q[][3],int n);        //函数原型为二维数组形参
	void main(void)
	{	double	b[2][3]={1,2,3,4,5,6};		 // sum(b+1,1)求区间{4,5,6}的和	     	
  	    printf("%2.0f,%2.0f\n",sum(b,2),sum(b+1,1));	//输出:21,15
		double	a[]={1,2,3,4,5,6,7};	    //(QA)a是强制类型转换,匹配形参的类型
		typedef double (*QA)[3];        //声明double (*)[3]型的别名QA
  	    printf("%2.0f,%2.0f\n",sum((QA)a,2),sum((QA)(a+4),1));	//输出:21,18
	} //sum((QA)a,2)求内存区间{1,2,3,4,5,6}之和;sum((QA)(a+4),1)求内存区间{5,6,7}之和
	double sum(double (*q)[3],int n)   // 函数定义为数组指针形参
	{ 	double s=0 ;int i,j;double *p;
		for( i=0;i<n;i++,q++)      //q++指向内存空间的下一行,即前移3*8=24个字节。
		for(j=0,p=*q;j< 3;j++,p++)  // p=*q得到该当前行的首地址,*q的值等于q的值。  
			    s+=*p;         //p++指向double型数组的下一个元素
		return s;                 //*p得到该位置元素的值
	}//sum函数与sum1函数完成相同的功能,但sum的效率高,sum1简洁。
	double sum1(double (*q)[3],int n)   // 函数定义为数组指针形参
	{ 	double s=0 ;                     //下标法求数组的和
		for(int i=0;i<n;i++) for(int j=0;j<3;j++)  s+=q[i][j];
		return s;
	}
//[例6.12] typedef简化数组定义
	# include <iostream.h>    
    const int L=2,M=2,N=2;//声明全局性的整型常数L,M,N
	typedef int ALMN[L][M][N];	typedef int (*PMN)[M][N];	typedef int (*PN)[N];
	void main(void)
 	{	int  j, k;	
	    ALMN  v= {1, 2,3, 4,5,6,7,8};	//定义三维数组v[L][M][N]同时初始化
	    PMN d=v;                         // 相当于 int (*d)[M][N]=v;
	    PN  a= v[1];                       //相当于int (*a)[N]=v[1];
		for (j=0;j<M;j++)  for (k=0;k<N; k++)      cout<<d[1][j][k]<<"," ;		
		for (j=0;j<M;j++)	for(k = 0; k <N; k++)     cout<<a[j][k]<<";"  ; 	
	 }	///输出结果: 5 ,6 ,7 ,8, 5 ;6 ;7 ;8;

//[例6.13] 指针数组的元素指向维数大小不同的一维数组

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -