转载了N多指针相关的东东

一、基础能力训练:
	编写一个程序实现功能:将字符串"Computer Secience"赋给一个字符数组,然后从第一个字母开始间隔的输出该串,用指针完成。
#include <stdio.h>
#include <string.h>

int main()
{
	char str[]="Computer Science";
    int flag=1;
	char *p=str;

	while(*p)
	{
	   if ( flag )
	   { 
    	  printf("%c",*p);
       }
       flag = (flag + 1) % 2;
       p++;
    }
	printf("\n");
    return 0;
}


  

用指针将数组s[8]={1,2,3,4,5,6,7,8}中的值逆序存放。
	#include <stdio.h>
	
	int main()
	{
	    int s[8]={1,2,3,4,5,6,7,8};
	    int *p,*q,count,swap;
	
	    count = sizeof(s)/sizeof(int);
	    p=s; q=s+count-1;
	    while( p < q )
	    {
	       swap = *p;
	       *p = *q;
	       *q = swap;
	       p++;
	       q--;
	     }
	
	     for(p=s; p<s+count; p++)  printf("%d ", *p);
	
	     return 0;
	}
	
	
3)编写一个程序实现功能:将两个字符串合并为一个字符串并且输出,用指针实现。
	   char str1[20]={"Hello "}, str2[20]={"World "};
	
	#include <stdio.h>
	
	int main()
	{
	   char str1[20]={"Hello "}, str2[20]={"World "};
	   char *p=str1, *q=str2;
	
	   while( *p ) p++;
	   while( *q ) 
	   {
	      *p = *q;
	      p++;
	      q++;
	    }
	    *p = '\0';
	    printf("%s\n", str1);
	
	    return 0;
	}
	
4) 编写一个程序实现以下功能:用指针数组处理一个二维数组,要求求出二维数组所有元素的和。
	        int array[3][4]={ {7,  10, -2,   3},
	                          {14, 30,  6, -15},
	                          {0,   5,  27, -7}
                         }  
#include <stdio.h>

int main()
{
  int array[3][4]={{7,10,-2,3},{14,30,6,-15},{0,5,27,-7}};
  int *pa[3]={array[0], array[1], array[2]}, i, j;
  int sum=0;

  for(i=0;i<3;i++)
  {
    for(j=0;j<4;j++,pa[i]++)
    {
      sum+=*pa[i];
    }
  }
  printf("%d\n",sum);
  return 0;
}


已知数组a[10]和b[10]中元素的值递增有序,用指针实现将两个数组中的元素按递增的顺序输出。

#include <stdio.h>

int main()
{
   int a[10]={1,  4,  12,  13,  14,  20,  25,  32,  33,  40};
   int b[10]={0,  3,  15,  18,  19,  25,  39,  43,  44,  50};
   int *p=a, *q=b;

   while( (p < (a+10)) && (q < (b+10)) )
   {
      if( *p < *q )
      {
         printf("%d ", *p);
         p++;
      }
      else
      {
         printf("%d ", *q);
         q++;
      }
   }

   if( p = = (a+10) )
   {
      p = q;
      q = b;
   }
   else
   {
      q = a;
   }

   while( p < (q+10) )
   {
      printf("%d ", *p++);
   }

   printf("\n");
   return 0;
}


6) 定义字符指针数组char *str[5]分别指向5个字符串常量,从小到大输出字符串的内容。

   #include <stdio.h>

	int main()
	{
      int i,j,min;
      char *str[5]={ "Shanghai",
                  "Beijing",
                  "Guangzhou",
                  "Tianjin",
                  "Chongqin"
                };
      char *p;

      for(i=0;i<4;i++)
      {
         min = i;

         for(j=i+1;j<5;j++ )
         {
            if( strcmp(str[min],str[j]) > 0 )
            {
               min = j;
            }
         }
         p = str[i];
         str[i] = str[min];
         str[min] = p;
      }

     for(i=0;i<5;i++)
     {
        printf("%s\n", str[i]);
     }

     return 0;
	}


7)  已知数组内容如下s[]={1,2,3,4,5,6,7,8,9}, 输入一个数n(1 <= n <= 9),
使得该数组内容顺序后移n个位置。
如n=3时,数组后移3个位置后的内容为{7,8,9,1,2,3,4,5,6}

#include <stdio.h>
#include <stdlib.h>

#define LEN 9 

int main()
{
   int array[LEN]={1,2,3,4,5,6,7,8,9};
   int i,num,temp,*p;

   printf("Please input the number(1-9) of elements you want to move:");
   scanf("\n%d", &num);

   if((num < 1 ) || (num > 9))
   {
      printf("The number is out of range(1-9), exit...\n");
      exit(0);
   }

   for(i=0;i<num;i++)
   {
      temp = *(array+LEN-1);
      for(p=array+LEN-1;p>array;p--)
      {
         *p = *(p-1);
      }
      *p = temp;
   }

   for(p=array;p<array+LEN;p++) printf("%d ", *p);
   printf("\n");

   return 0;
}



8)  输入一个字符串,内有数字和非数字字符,如 a123x456 17960? 302tab5876  将
其中连续的数字作为一个整数,依次存放到整型数组a中。例如,123放在a[0],456放在a[1],统计共有多少个整数,并输出这些数。

#include <stdio.h>

#define LEN 80

int main()
{
   char str[LEN],*p;
   int array[LEN/2],value=0,n=0;
   int begin_count=0; 

   printf("Please input a string which including any digits:\n");
   gets(str);
   //printf("%s\n", str);
   p = str;
   while( *p )
   {
      if ((*p >= '0') && (*p <= '9'))
      {
         begin_count = 1;
         value = value*10 + *p - '0';
      }
      else
      {
         if ( begin_count = = 1)
         {
            array[n++]=value;
            begin_count = 0;
            value = 0;
         }
      }
      p++;  
   }
   if (begin_count = = 1) array[n++]=value;
   for(value=0;value<n;value++) printf("%d ", array[value]);
   printf("\n");   

   return 0;
}

//==========================================================================
试验九  函数
1) 编写函数分别实现以下功能:(1)求两个浮点数之和;(2)求两个浮点数之差;(3)求两个浮点数之积。
	
	#include <stdio.h>
	double add(double a, double b)
	{
		return a+b;
	}
	double subtract(double a, double b)
	{
		return a-b;
	}
	double multiple(double a,double b)
	{
		return a*b;
	}
	int main()
	{
		double num1,num2;
		printf("please input tow number:");
		scanf("%lf %lf",&num1,&num2);
		printf("%5.2f + %5.2f = %5.2f\n",num1,num2,add(num1,num2));
		printf("%5.2f + %5.2f = %5.2f\n",num1,num2,subtract(num1,num2));
		printf("%5.2f + %5.2f = %5.2f\n",num1,num2,multiple(num1,num2));
	}
	
	
2) 编写一个函数,包括一个字符参数和两个整型参数。字符参数是需要输出的字符,
第一个整型参数说明了在每行中该字符输出的个数,而第二个整型参数指的是需要输
出的行数,编写一个调用该函数的程序。
#include <stdio.h>
int main(void)    
{
	char ch;
	int i, j, col, row;
	    
printf("Enter a character : ");
	ch = getchar();           
	printf("Enter number of columns and number of rows: ");
	if (scanf("%d %d", &col, &row) != 2) return -1;
	for (i = 0; i < row ; i++)
	{
	for (j = 0; j < col; j++)
	{
	    putchar(ch);
	}
        putchar('\n');
	}
	return 0;
	}



3) 编写一个函数taxis()实现数组的排序,在函数中调用swap()实现两个数的交换。
打印出排序结果。

#include <stdio.h>

void swap(int *a,int *b)
{
	int tmp;
	tmp=*a;
	*a=*b;
	*b=tmp;
}

void taxis(int *a, int num)
{
	int i,j;
	for(i=0;i<num-1;i++)
	{
		for(j=i+1;j<num;j++)
		{
			if(a[i] > a[j])
				swap(&a[i],&a[j]);
}
}
}

int main()
{
	int i,a[]={2,5,9,8,7,6,4,3,1};
	taxis(a, sizeof(a)/sizeof(int));
	for(i=0;i<sizeof(a)/sizeof(int);i++)
	{
		printf("%d\t",a[i]);
}
printf("\n");
return 0;
}



4) 编写一个函数,实现两个字符串的比较。

	#include <stdio.h>
	int my_strcmp(char *p,char *q)
	{
		int i=0;;
		
		while(*(p+i) == *(q+i))
	    {
		   if( *(p+i) = ='\0' )  return 0;
           i++;
        } 
		return(*(p+i) - *(q+i));
	}
	
	int main()
	{
		int m;
	char str1[20],str2[20];
	
		printf("Input tow strings:");
		gets(str1);
	    gets(str2);
		printf("result:%d\n",my_strmp(str1,str2));
	    return 0;
	}



编写一个函数is-within().它接受两个参数,一个是字符,
另一个是字符串指针。其功能是如果字符在字符串中。
就返回1(真);如果字符不在字符串中,就返回0(假)。
在一个使用循环语句为这个函数提供输入的完整程序中进行测试。

	#include <stdio.h>
	#define  LEN  80
	int is_within(const char * str, char c);
	int main(void)
	{
	    char input[LEN];
	    char ch;
	    int found;;
	    
	    printf("Enter a string: ");
	    while (gets(input) && input[0] != '\0')
	    {
	        printf("Enter a character: ");
	        scanf("\n%c",  &ch);
	        found = is_within(input, ch);
	        if (found = = 0)
	            printf("%c not found in string.\n", ch);
	        else
	            printf("%c found in string %s\n", ch, input);
	        printf("Next string: ");
	    }
	    puts("Done.\n");
	    
	    return 0;
	}
	
	int is_within(const char * str, char ch)
	{
	    while (*str != ch && *str != '\0')
	    {
	        str++;
	    }
	    return *str;   /* = 0  if '\0'is reached, non-zero otherwise */
	}



输出程序运行时的命令行参数。例如:
./myprog  a  b  c
a  b  c

#incldue <stdio.h>
int main(int argc,char *argv[])
{   int i = 1;
	while( i < argc )
	{
		printf("%s ",argv[i]);
		i++;
	}
	printf("\n");
	return 0;
}	



7) 以下函数的功能是用递归的方法计算x的n阶勒让德多项式的值。已有调用语句p(n,x);编写函数实现功能。递归公式如下:
	
	
	
	#include <stdio.h>
	
	float p(int x,int n)
	{
		float t,t1,t2;
		if(n= =0) return 1;
		else if(n= =1) return x;
		else 
		{
			t1=(2*n-1)*x*p(x,(n-1));
			t2=(n-1)*p(x,(n-2));
			t=(t1-t2)/n;
			return t;
	}
	}
	
	int main()
	{
		int x,n;
		printf("input two int (x and n):");
		scanf("%d%d",&x,&n);
		printf("%.2f\n",p(x,n));
		return 0;
	}
	//===========================================================
	指针函数和函数指针的区别(转载)
1,这两个概念都是简称,指针函数是指带指针的函数,即本质是一个函数。
我们知道函数都又返回类型(如果不返回值,则为无值型),
只不过指针函数返回类型是某一类型的指针。其定义格式如下所示:

返回类型标识符 *返回名称(形式参数表) 
{ 函数体 }

  返回类型可以是任何基本类型和复合类型。返回指针
的函数的用途十分广泛。事实上,每一个函数,即使它不
带有返回某种类型的指针,它本身都有一个入口地址,该
地址相当于一个指针。比如函数返回一个整型值,实际上
也相当于返回一个指针变量的值,不过这时的变量是函数
本身而已,而整个函数相当于一个“变量”。例如下面一
个返回指针函数的例子:

#include

float *find(); 
main() 
{ 
  static float score[][4]={{60,70,80,90},{56,89,34,45},{34,23,56,45}}; 
  float *p; 
  int i,m; 
  printf("Enter the number to be found:"); 
  scanf("%d",&m); 
  printf("the score of NO.%d are:\n",m); 
  p=find(score,m); 
  for(i=0;i<4;i++) 
    printf("%5.2f\t",*(p+i)); 
}

float *find(float(*pionter)[4],int n)/*定义指针函数*/ 
{ 
  float *pt; 
  pt=*(pionter+n); 
  return(pt); 
}

  学生学号从0号算起,函数find()被定义为指针函数,起形参
pointer是指针指向包含4个元素的一维数组的指针变量。
pointer+1指向score的第一行。*(pointer+1)指向第一行的第0个元素。
pt是一个指针变量,它指向浮点型变量。main()函数中调用find()函数,
将score数组的首地址传给pointer.

2,“函数指针”是指向函数的指针变量,因而“函数指针”
本身首先应是指针变量,只不过该指针变量指向函数。
这正如用指针变量可指向整型变量、字符型、数组一样,
这里是指向函数。如前所述,C在编译时,每一个函数都有
一个入口地址,该入口地址就是函数指针所指向的地址。
有了指向函数的指针变量后,可用该指针变量调用函数,
就如同用指针变量可引用其他类型变量一样,在这些概念
上一致的。函数指针有两个用途:调用函数和做函数的参
数。函数指针的说明方法为: 
数据类型标志符 (*指针变量名)(参数);
注:函数括号中的参数可有可无,视情况而定。 
下面的程序说明了函数指针调用函数的方法:

#include"stdio.h"
                                                  
int max1(int x,int y)
{ return(x>y?x:y); }
int max2(int x,int y)
{ return(x>y?x:y); }
void main() 
{ 
  int (*ptr)(); 
  int a,b,c; 
  ptr=max1; 
  scanf("%d,%d",&a,&b); 
  c=(*ptr)(a,b); 
  printf("a=%d,b=%d,max=%d",a,b,c); 
  ptr=max2; 
  scanf("%d,%d",&a,&b); 
  c=(*ptr)(a,b); 
  printf("a=%d,b=%d,max=%d",a,b,c); 
}

  ptr是指向函数的指针变量,所以可把函数max()
赋给ptr作为ptr的值,即把max()的入口地址赋给ptr,
以后就可以用ptr来调用该函数,实际上ptr和max都指
向同一个入口地址,不同就是ptr是一个指针变量,
不像函数名称那样是死的,它可以指向任何函数,
就看你像怎么做了。在程序中把哪个函数的地址赋给它,
它就指向哪个函数。而后用指针变量调用它,因此可以
先后指向不同的函数,不过注意,指向函数的指针变量没
有++和--运算,用时要小心。




指针函数是指函数的返回值类型是一个指针类型,即本质是一个函数。
  我们知道函数都有返回类型(如果不返回值,则为无值型),
只不过指针函数返回类型是某一类型的指针。其定义格式如下所示:
  返回类型标识符 *函数名称(形式参数表)
  { 函数体 }
  返回类型可以是任何基本类型和复合类型。
返回指针的函数的用途十分广泛。事实上,每一个函数,
即使它不带有返回某种类型的指针,它本身都有一个入
口地址,该地址相当于一个指针。比如函数返回一个整型
值,实际上也相当于返回一个指针变量的值,不过这时的
变量是函数本身而已,而整个函数相当于一个“变量”。
例如下面一个返回指针函数的例子:
#include <stdio.h>
  float *find(float(*pionter)[4],int n);
  main()
  {
  static float score[][4]={{60,70,80,90},{56,89,34,45},{34,23,56,45}};
  float *p;
  int i,m;
  printf("Enter the number to be found:");
  scanf("%d",&m);
  printf("the score of NO.%d are:\n",m);
  p=find(score,m-1);
  for(i=0;i<4;i++)
  printf("%5.2f\t",*(p+i));
  }
  float *find(float(*pionter)[4],int n)/*定义指针函数*/
  {
  float *pt;
  pt=*(pionter+n);
  return(pt);
  }
共有三个学生的成绩,函数find()被定义为指针函数,起
形参pointer是指针指向包含4个元素的一维数组的指针变
量。pointer+n指向score的第n+1行。*(pointer+1)指向第
一行的第0个元素。pt是一个指针变量,它指向浮点型变量。
main()函数中调用find()函数,将score数组的首地址传
给pointer.
  【注意】
  指针函数不同于函数指针, int (*f)(int a);
或者char (*f1)(void);
  函数指针声明为指针,它与变量指针不同之处是,
它不是指向变量,而是指向函数。
  函数指针有两个用途:调用函数和做函数的参数.
百科名片

函数指针

函数指针是指向函数的指针变量。 因而“函数指针”本身首
先应是指针变量,只不过该指针变量指向函数。这正如用指针
变量可指向整型变量、字符型、数组一样,这里是指向函数。
如前所述,C在编译时,每一个函数都有一个入口地址,该入
口地址就是函数指针所指向的地址。有了指向函数的指针变量后,
可用该指针变量调用函数,就如同用指针变量可引用其他类型变量
一样,在这些概念上是一致的。函数指针有两个用途:调用函数和
做函数的参数。

目录

方法
指针函数和函数指针的区别
关于函数指针数组的定义
  方法
  函数指针的声明方法为:   
数据类型标志符 (指针变量名) (形参列表);   
注1:“函数类型”说明函数的返回类型,由于“()”的优先级高于“*”,
所以指针变量名外的括号必不可少,后面的“形参列表”表示指针变量
指向的函数所带的参数列表。例如:   
int func(int x); /* 声明一个函数 */   
int (*f) (int x); /* 声明一个函数指针 */   
f=func; /* 将func函数的首地址赋给指针f */   
赋值时函数func不带括号,也不带参数,由于func代表函数的首地址,
因此经过赋值以后,指针f就指向函数func(x)的代码的首地址。   
注2:函数括号中的形参可有可无,视情况而定。   
下面的程序说明了函数指针调用函数的方法:   
例一、   
#include<stdio.h>   
int max(int x,int y)
{ return(x>y?x:y); }   
void main()   
{   
int (*ptr)(int, int);   
int a,b,c;   
ptr=max;   
scanf("%d,%d",&a,&b);   
c=(*ptr)(a,b);   
printf("a=%d,b=%d,max=%d",a,b,c);   
}   
ptr是指向函数的指针变量,所以可把函数max()赋给ptr作为ptr的值,
即把max()的入口地址赋给ptr,以后就可以用ptr来调用该函数,实际
上ptr和max都指向同一个入口地址,不同就是ptr是一个指针变量,
不像函数名称那样是死的,它可以指向任何函数,就看你想怎么做了。
在程序中把哪个函数的地址赋给它,它就指向哪个函数。而后用指针变
量调用它,因此可以先后指向不同的函数。不过注意,指向函数的指针
变量没有++和--运算,用时要小心。


   
不过,在某些编译器中这是不能通过的。这个例子的补充如下。   
应该是这样的:   
1.定义函数指针类型:   
typedef int (*fun_ptr)(int,int);   
2.申明变量,赋值:   
fun_ptr max_func=max;   

也就是说,赋给函数指针的函数应该和函数指针所指的函数原型是一致的。   
例二、   
#include<stdio.h>   
void FileFunc()   
{   printf("FileFunc\n");   }   
void EditFunc()   
{   printf("EditFunc\n");   }   
void main()   
{   
typedef void (*funcp)();   
funcp=FileFunc;   
(*funcp)();   
funcp=EditFunc;   
(*funcp)();   
}
 指针函数和函数指针的区别
  1,这两个概念都是简称,指针函数是指带指针的函数,即本质是一
个函数。我们知道函数都又有返回类型(如果不返回值,则为无值型),
只不过指针函数返回类型是某一类型的指针。   
其定义格式如下所示:   
返回类型标识符 *返回名称(形式参数表)   
{ 函数体 }   
返回类型可以是任何基本类型和复合类型。返回指针的函数的用途十分广泛。
事实上,每一个函数,即使它不带有返回某种类型的指针,它本身都有一个入
口地址,该地址相当于一个指针。比如函数返回一个整型值,实际上也相当于
返回一个指针变量的值,不过这时的变量是函数本身而已,而整个函数相当于
一个“变量”。
例如下面一个返回指针函数的例子:   
#include<iostream>   
using namespace std;   
void main()   
{   
float *find(float(*pionter)[4],int n);   
static float score[][4]={{60,70,80,90},{56,89,34,45},{34,23,56,45}};   
float *p;   
int i,m;   
cout<<"Enter the number to be found:";   
cin>>m;   
p=find(score,m);   
for(i=0;i<4;i++)   
cout<<" "<<*(p+i);   
}   
float *find(float(*pionter)[4],int n)/*定义指针函数*/   
{   float *pt;   pt=*(pionter+n);   return(pt);   }   
学生学号从0号算起,函数find()被定义为指针函数,起形参pointer是指
针指向包含4个元素的一维数组的指针变量。pointer+1指向 score的第一行。
*(pointer+1)指向第一行的第0个元素。pt是一个指针变量,它指向浮点型变
量。
main()函数中调用find()函数,将score数组的首地址传给pointer.   
2,“函数指针”是指向函数的指针变量,因而“函数指针”本身首先应是指针
变量,只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符
型、数组一样,这里是指向函数。如前所述,C在编译时,每一个函数都有一个
入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量
后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,
在这些概念上一致的。函数指针有两个用途:调用函数和做函数的参数。
 关于函数指针数组的定义
  关于函数指针数组的定义方法,有两种:一种是标准的方法;一种是蒙
骗法。   
第一种,标准方法:   
{   分析:函数指针数组是一个其元素是函数指针的数组。
	那么也就是说,此数据结构是一个数组,且其元素是一个
	指向函数入口地址的指针。   
	根据分析:首先说明是一个数组:数组名[]   
	其次,要说明其元素的数据类型指针:*数组名[].   
		再次,要明确这每一个数组元素是指向函数入口地址
		的指针:函数返回值类型 (*数组名[])().请注意,
		这里为什么要把“*数组名[]”用括号扩起来呢?
		因为圆括号和数组说明符的优先级是等同的,如果
		不用圆括号把指针数组说明表达式扩起来,根据圆括
		号和方括号的结合方向,那么 *数组名[]() 说明的
		是什么呢?是元素返回值类型为指针的函数数组。
		有这样的函数数祖吗?不知道。所以必须括起来,
		以保证数组的每一个元素是指针。   }   
		第二种,蒙骗法:   尽管函数不是变量,但它在内存
		中仍有其物理地址,该地址能够赋给指针变量。获取函数
		地址的方法是:用不带有括号和参数的函数名得到。   
		函数名相当于一个指向其函数入口指针常量。 那么既然
		函数名是一个指针常量,那么就可以对其进行一些相应的
		处理,如强制类型转换。   
		那么我们就可以把这个地址放在一个整形指针数组中,
		然后作为函数指针调用即可。   完整例子:   
		#include "stdio.h"   
		int add1(int a1,int b1);   
		int add2(int a2,int b2);   
		void main()   
		{   
			int numa1=1,numb1=2;   
			int numa2=2,numb2=3;   
			int (*op[2])(int a,int b);   
			op[0]=add1;   
			op[1]=add2;   
			printf("%d %d\n",op[0](numa1,numb1),op[1](numa2,numb2));   
			}   
			int add1(int a1,int b1)   
			{   return a1+b1;   }
			   int add2(int a2,int b2)   
			 {   return a2+b2;   }
//




指针是一个特殊的变量,它里面存储的数值被解释成为内存里
的一个地址。   
要搞清一个指针需要搞清指针的四方面的内容
:指针的类型,指针所指向的   
  类型,指针的值或者叫指针所
  指向的内存区,
  还有指针本身所占据的内存区。让我们分别说明。   
  先声明几个指针放着做例子:   
  例一:   
  (1)int*ptr;   
  (2)char*ptr;   
  (3)int**ptr;   
  (4)int(*ptr)[3];   
  (5)int*(*ptr)[4];   
   
  指针的类型 
  从语法的角度看,你只要把指针声明语句里的指针名字去掉,
剩下的部分就是这个指针的类型。这是指针本身所具有的类型。
让我们看看例一中各个指针的类型:   
  (1)int*ptr;//指针的类型是int*   
  (2)char*ptr;//指针的类型是char*   
  (3)int**ptr;//指针的类型是int**   
  (4)int(*ptr)[3];//指针的类型是int(*)[3]   
  (5)int*(*ptr)[4];//指针的类型是int*(*)[4]   
  怎么样?找出指针的类型的方法是不是很简单?   
  指针所指向的类型 
  当你通过指针来访问指针所指向的内存区时,指针所指向的类
型决定了编译器将把那片内存区里的内容当做什么来看待。   
  从语法上看,你只须把指针声明语句中的指针名字和名字左边
的指针声明符*去掉,剩下的就是指针所指向的类型。例如:   
  (1)int*ptr;//指针所指向的类型是int   
  (2)char*ptr;//指针所指向的的类型是char   
  (3)int**ptr;//指针所指向的的类型是int*   
  (4)int(*ptr)[3];//指针所指向的的类型是int()[3]   
  (5)int*(*ptr)[4];//指针所指向的的类型是int*()[4]   
  在指针的算术运算中,指针所指向的类型有很大的作用。   
  指针的类型(即指针本身的类型)和指针所指向的类型是两个概念
。当你对C越来越熟悉时,你会发现,把与指针搅和在一起的 "类型 "
这个概念分成 "指针的类型 "和 "指针所指向的类型
 "两个概念,是精通指针的关键点之一。我看了不少书,发
现有些写得差的书中,就把指针的这两个概念搅在一起了,所以看
起书来前后矛盾,越看越糊涂。
指针的值,或者叫指针所指向的内存区或地址指针的值是指针本身
存储的数值,这个值将被编译器当作一个地址,而不是一个一般的数
值。在32位程序里,所有类型的指针的值都是一个32位整数,因为32
位程序里内存地址全都是32位长。   
指针所指向的内存区就是从指针的值所代表的那个
内存地址开始,长度为sizeof(指针所指向的类型)的一片内存区。
以后,我们说一个指针的值是XX,就相当于说该指针指
向了以XX为首地址的一片内存区域;我们说一个指针指向了某块内
存区域,就相当于说该指针的值是这块内存区域的首地址。   
  指针所指向的内存区和指针所指向的类型是两个完全不同的概
念。在例一中,指针所指向的类型已经有了,但由于指针
还未初始化,所以它所指向的内存区是不存在的,或者说是无意义的。   
  以后,每遇到一个指针,都应该问问:这个指针的类型是什么?
指针指的类型是什么?该指针指向了哪里?   
  指针本身所占据的内存区 
  指针本身占了多大的内存?你只要用函数sizeof(指针的类型)
测一下就知道了。在32位平台里,指针本身占据了4个字节
的长度。   
  指针本身占据的内存这个概念在判断一个指针表达式是否是左
值时很有用。   
  指针的算术运算   
指针可以加上或减去一个整数。指针的这种运算的意义和通常的数
值的加减运算的意义是不一样的。例如:   
  例二:   
  1、char a[20];   
  2、int *ptr=a;   
  ...   
 ...   
  3、ptr++;   
  在上例中,指针ptr的类型是int*,它指向的类型是int,它被初始化为指向整形变量a。接下来的第3句中,指针ptr
被加了1,编译器是这样处理的:它把指针ptr的值加上了sizeof(int),在32位程序中,是被加上了4。由于地址是用字
节做单位的,故ptr所指向的地址由原来的变量a的地址向高地址方向增加了4个字节。   
由于char类型的长度是一个字节,所以,原来ptr是指向数组a的第0号单元开始的四个字节,此时指向了数组a中从第4
号单元开始的四个字节。   
  我们可以用一个指针和一个循环来遍历一个数组,看例子: 
  例三:   
intarray[20];   
int*ptr=array;   
...   
//此处略去为整型数组赋值的代码。   
...   
for(i=0;i <20;i++)   
{   
 (*ptr)++;   
 ptr++;   
} 
  这个例子将整型数组中各个单元的值加1。由于每次循环都将指针ptr加1,所以每次循环都能访问数组的下一个单元。   

  再看例子:   

  例四:   

  1、chara[20];   
  2、int*ptr=a;   
  ...   
  ...   
  3、ptr+=5; 
  在这个例子中,ptr被加上了5,编译器是这样处理的:将指针ptr的值加上5乘sizeof(int),在32位程序中就是加上
了5乘4=20。由于地址的单位是字节,故现在的ptr所指向的地址比起加5后的ptr所指向的地址来说,向高地址方向移动了
20个字节。在这个例子中,没加5前的ptr指向数组a的第0号单元开始的四个字节,加5后,ptr已经指向了数组a的合法范
围之外了。虽然这种情况在应用上会出问题,但在语法上却是可以的。这也体现出了指针的灵活性。
如果上例中,ptr是被减去5,那么处理过程大同小异,只不过ptr的值是被减去5乘sizeof(int),新的ptr指向的地址将比原来的ptr所指向的地址向低地址方向移动了20个字节。   
  总结一下,一个指针ptrold加上一个整数n后,结果是一个新的指针ptrnew,ptrnew的类型和ptrold的类型相同,ptrnew所指向的类型和ptrold所指向的类型也相同。ptrnew的值将比ptrold的值增加了n乘sizeof(ptrold所指向的类型)个字节。就是说,ptrnew所指向的内存区将比ptrold所指向的内存区向高地址方向移动了n乘sizeof(ptrold所指向的类型)个字节。   
  一个指针ptrold减去一个整数n后,结果是一个新的指针ptrnew,ptrnew的类型和ptrold的类型相同,ptrnew所指向的类型和ptrold所指向的类型也相同。ptrnew的值将比ptrold的值减少了n乘sizeof(ptrold所指向的类型)个字节,就是说,ptrnew所指向的内存区将比ptrold所指向的内存区向低地址方向移动了n乘sizeof(ptrold所指向的类型)个字节。   
运算符&和*   
这里&是取地址运算符,*是...书上叫做 "间接运算符 "。   
  &a的运算结果是一个指针,指针的类型是a的类型加个*,指针所指向的类型是a的类型,指针所指向的地址嘛,那就是a的地址。   
  *p的运算结果就五花八门了。总之*p的结果是p所指向的东西,这个东西有这些特点:它的类型是p指向的类型,它所占用的地址是p所指向的地址。   
  例五:   
inta=12;   
intb;   
int*p; 
int**ptr;   
p=&a; 
//&a的结果是一个指针,类型是int*,指向的类型是int,指向的地址是a的地址。   
*p=24; 
//*p的结果,在这里它的类型是int,它所占用的地址是p所指向的地址,显然,*p就是变量a。   
ptr=&p; 
//&p的结果是个指针,该指针的类型是p的类型加个*,在这里是int   **。该指针所指向的类型是p的类型,这里是int*。该指针所指向的地址就是指针p自己的地址。   
*ptr=&b; 
//*ptr是个指针,&b的结果也是个指针,且这两个指针的类型和所指向的类型是一样的,所以用&b来给*ptr赋值就是毫无问题的了。   
**ptr=34; 
//*ptr的结果是ptr所指向的东西,在这里是一个指针,对这个指针再做一次*运算,结果就是一个int类型的变量。 
  指针表达式   
一个表达式的最后结果如果是一个指针,那么这个表达式就叫指针表式。   
  下面是一些指针表达式的例子:   
  例六:   
inta,b;   
intarray[10];   
int*pa;   
pa=&a;//&a是一个指针表达式。   
int**ptr=&pa;//&pa也是一个指针表达式。   
*ptr=&b;//*ptr和&b都是指针表达式。   
pa=array;   
pa++;//这也是指针表达式。 
例七:   
char*arr[20];   
char**parr=arr;//如果把arr看作指针的话,arr也是指针表达式   
char*str;   
str=*parr;//*parr是指针表达式   
str=*(parr+1);//*(parr+1)是指针表达式   
str=*(parr+2);//*(parr+2)是指针表达式 
  由于指针表达式的结果是一个指针,所以指针表达式也具有指针所具有的四个要素:指针的类型,指针所指向的类型,指针指向的内存区,指针自身占据的内存。 

  好了,当一个指针表达式的结果指针已经明确地具有了指针自身占据的内存的话,这个指针表达式就是一个左值,否则就不是一个左值。   
  在例七中,&a不是一个左值,因为它还没有占据明确的内存。*ptr是一个左值,因为*ptr这个指针已经占据了内存,其实*ptr就是指针pa,既然pa已经在内存中有了自己的位置,那么*ptr当然也有了自己的位置。   
  数组和指针的关系   
  数组的数组名其实可以看作一个指针。看下例:   
  例八:   
intarray[10]={0,1,2,3,4,5,6,7,8,9},value;   
...   
...   
value=array[0];//也可写成:value=*array;   
value=array[3];//也可写成:value=*(array+3);   
value=array[4];//也可写成:value=*(array+4); 
上例中,一般而言数组名array代表数组本身,类型是int[10],但如果把array看做指针的话,它指向数组的第0个单元,类型是int*,所指向的类型是数组单元的类型即int。因此*array等于0就一点也不奇怪了。同理,array+3是一个指向数组第3个单元的指针,所以*(array+3)等于3。其它依此类推。   

  例九:   
char*str[3]={   
  "Hello,thisisasample! ",   
  "Hi,goodmorning. ",   
  "Helloworld "   
};   
chars[80];   
strcpy(s,str[0]);//也可写成strcpy(s,*str);   
strcpy(s,str[1]);//也可写成strcpy(s,*(str+1));   
strcpy(s,str[2]);//也可写成strcpy(s,*(str+2)); 
上例中,str是一个三单元的数组,该数组的每个单元都是一个指针,这些指针各指向一个字符串。把指针数组名str当作一个指针的话,它指向数组的第0号单元,它的类型是char**,它指向的类型是char*。   
*str也是一个指针,它的类型是char*,它所指向的类型是char,它指向的地址是字符串 "Hello,thisisasample! "的第一个字符的地址,即 'H '的地址。   str+1也是一个指针,它指向数组的第1号单元,它的类型是char**,它指向的类型是char*。   

  *(str+1)也是一个指针,它的类型是char*,它所指向的类型是char,它指向   "Hi,goodmorning. "的第一个字符 'H ',等等。   

  下面总结一下数组的数组名的问题。声明了一个数组TYPEarray[n],则数组名称array就有了两重含义:第一,它代表整个数组,它的类型是TYPE[n];第二   ,它是一个指针,该指针的类型是TYPE*,该指针指向的类型是TYPE,也就是数组单元的类型,该指针指向的内存区就是数组第0号单元,该指针自己占有单独的内存区,注意它和数组第0号单元占据的内存区是不同的。该指针的值是不能修改的,即类似array++的表达式是错误的。   
  在不同的表达式中数组名array可以扮演不同的角色。   
  在表达式sizeof(array)中,数组名array代表数组本身,故这时sizeof函数测出的是整个数组的大小。   
在表达式*array中,array扮演的是指针,因此这个表达式的结果就是数组第0号单元的值。sizeof(*array)测出的是数组单元的大小。   
  表达式array+n(其中n=0,1,2,....?┲校琣rray扮演的是指针,故array+n的结果是一个指针,它的类型是TYPE*,它指向的类型是TYPE,它指向数组第n号单元。故sizeof(array+n)测出的是指针类型的大小。   
例十 
intarray[10];   
int(*ptr)[10];   
ptr=&array;:   
上例中ptr是一个指针,它的类型是int(*)[10],他指向的类型是int[10]   ,我们用整个数组的首地址来初始化它。在语句ptr=&array中,array代表数组本身。   

  本节中提到了函数sizeof(),那么我来问一问,sizeof(指针名称)测出的究竟是指针自身类型的大小呢还是指针所指向的类型的大小?答案是前者。例如:   
int(*ptr)[10];   
  则在32位程序中,有:   
sizeof(int(*)[10])==4   
sizeof(int[10])==40   
sizeof(ptr)==4 
实际上,sizeof(对象)测出的都是对象自身的类型的大小,而不是别的什么类型的大小。 
指针和结构类型的关系   
可以声明一个指向结构类型对象的指针。   
  例十一:   
structMyStruct   
{   
 inta;   
 intb;   
 intc;   
}   
MyStructss={20,30,40}; 
//声明了结构对象ss,并把ss的三个成员初始化为20,30和40。   
MyStruct*ptr=&ss; 
//声明了一个指向结构对象ss的指针。它的类型是MyStruct*,它指向的类型是MyStruct。   
int*pstr=(int*)&ss; 
//声明了一个指向结构对象ss的指针。但是它的类型和它指向的类型和ptr是不同的。 
  请问怎样通过指针ptr来访问ss的三个成员变量?   
  答案:   
ptr-> a;   
ptr-> b;   
ptr-> c;   
  又请问怎样通过指针pstr来访问ss的三个成员变量?   
  答案:   
*pstr;//访问了ss的成员a。   
*(pstr+1);//访问了ss的成员b。   
*(pstr+2)//访问了ss的成员c。   
  虽然我在我的MSVC++6.0上调式过上述代码,但是要知道,这样使用pstr来访问结构成员是不正规的,为了说明为什么不正规,让我们看看怎样通过指针来访问数组的各个单元:   
  例十二:   
intarray[3]={35,56,37};   
int*pa=array;   
  通过指针pa访问数组array的三个单元的方法是:   
*pa;//访问了第0号单元   
*(pa+1);//访问了第1号单元   
*(pa+2);//访问了第2号单元   
从格式上看倒是与通过指针访问结构成员的不正规方法的格式一样。   
  所有的C/C++编译器在排列数组的单元时,总是把各个数组单元存放在连续的存储区里,单元和单元之间没有空隙。但在存放结构对象的各个成员时,在某种编译环境下,可能会需要字对齐或双字对齐或者是别的什么对齐,需要在相邻两个成员之间加若干个 "填充字节 ",这就导致各个成员之间可能会有若干个字节的空隙。   
  所以,在例十二中,即使*pstr访问到了结构对象ss的第一个成员变量a,也不能保证*(pstr+1)就一定能访问到结构成员b。因为成员a和成员b之间可能会有若干填充字节,说不定*(pstr+1)就正好访问到了这些填充字节呢。这也证明了指针的灵活性。要是你的目的就是想看看各个结构成员之间到底有没有填充字节,嘿,这倒是个不错的方法。   
过指针访问结构成员的正确方法应该是象例十二中使用指针ptr的方法。   
  指针和函数的关系   
  可以把一个指针声明成为一个指向函数的指针。intfun1(char*,int);   
int(*pfun1)(char*,int);   
pfun1=fun1;   
....   
....   
inta=(*pfun1)( "abcdefg ",7);//通过函数指针调用函数。   
可以把指针作为函数的形参。在函数调用语句中,可以用指针表达式来作为实参。   
  例十三:   
intfun(char*);   
inta;   
charstr[]= "abcdefghijklmn ";   
a=fun(str);   
...   
...   
intfun(char*s)   
{   
intnum=0;   
for(inti=0;i{   
num+=*s;s++;   
}   
returnnum; 
} 
  这个例子中的函数fun统计一个字符串中各个字符的ASCII码值之和。前面说了,数组的名字也是一个指针。在函数调用中,当把str作为实参传递给形参s后,实际是把str的值传递给了s,s所指向的地址就和str所指向的地址一致,但是str和s各自占用各自的存储空间。在函数体内对s进行自加1运算,并不意味着同时对str进行了自加1运算。 
指针类型转换   
当我们初始化一个指针或给一个指针赋值时,赋值号的左边是一个指针,赋值号的右边是一个指针表达式。在我们前面所举的例子中,绝大多数情况下,指针的类型和指针表达式的类型是一样的,指针所指向的类型和指针表达式所指向的类型是一样的。   
  例十四:   
  1、floatf=12.3;   
  2、float*fptr=&f;   
  3、int*p;   
   在上面的例子中,假如我们想让指针p指向实数f,应该怎么搞?是用下面的语句吗?   

  p=&f;   

  不对。因为指针p的类型是int*,它指向的类型是int。表达式&f的结果是一个指针,指针的类型是float*,它指向的类型是float。两者不一致,直接赋值的方法是不行的。至少在我的MSVC++6.0上,对指针的赋值语句要求赋值号两边的类型一致,所指向的类型也一致,其它的编译器上我没试过,大家可以试试。为了实现我们的目的,需要进行 "强制类型转换 ":   
p=(int*)&f; 
如果有一个指针p,我们需要把它的类型和所指向的类型改为TYEP*TYPE,   那么语法格式是:   
  (TYPE*)p;   
  这样强制类型转换的结果是一个新指针,该新指针的类型是TYPE*,它指向的类型是TYPE,它指向的地址就是原指针指向的地址。而原来的指针p的一切属性都没有被修改。   
  一个函数如果使用了指针作为形参,那么在函数调用语句的实参和形参的结合过程中,也会发生指针类型的转换。   
  例十五: 
voidfun(char*);   
inta=125,b;   
fun((char*)&a);   
...   
...   
voidfun(char*s)   
{   
charc;   
c=*(s+3);*(s+3)=*(s+0);*(s+0)=c;   
c=*(s+2);*(s+2)=*(s+1);*(s+1)=c;   
}   
}   
注意这是一个32位程序,故int类型占了四个字节,char类型占一个字节。函数fun的作用是把一个整数的四个字节的顺序来个颠倒。注意到了吗?在函数调用语句中,实参&a的结果是一个指针,它的类型是int*,它指向的类型是int。形参这个指针的类型是char*,它指向的类型是char。这样,在实参和形参的结合过程中,我们必须进行一次从int*类型到char*类型的转换。结合这个例子,我们可以这样来想象编译器进行转换的过程:编译器先构造一个临时指针char*temp,   然后执行temp=(char*)&a,最后再把temp的值传递给s。所以最后的结果是:s的类型是char*,它指向的类型是char,它指向的地址就是a的首地址。   

  我们已经知道,指针的值就是指针指向的地址,在32位程序中,指针的值其实是一个32位整数。那可不可以把一个整数当作指针的值直接赋给指针呢?就象下面的语句: 
unsignedinta;   
TYPE*ptr;//TYPE是int,char或结构类型等等类型。   
...   
...   
a=20345686;   
ptr=20345686;//我们的目的是要使指针ptr指向地址20345686(十进制   
)   
ptr=a;//我们的目的是要使指针ptr指向地址20345686(十进制) 
编译一下吧。结果发现后面两条语句全是错的。那么我们的目的就不能达到了吗?不,还有办法:   
unsignedinta;   
TYPE*ptr;//TYPE是int,char或结构类型等等类型。   
...   
...   
a=某个数,这个数必须代表一个合法的地址;   
ptr=(TYPE*)a;//呵呵,这就可以了。 
严格说来这里的(TYPE*)和指针类型转换中的(TYPE*)还不一样。这里的(TYPE*)的意思是把无符号整数a的值当作一个地址来看待。上面强调了a的值必须代表一个合法的地址,否则的话,在你使用ptr的时候,就会出现非法操作错误。   

  想想能不能反过来,把指针指向的地址即指针的值当作一个整数取出来。完   全可以。下面的例子演示了把一个指针的值当作一个整数取出来,然后再把这个整数当作一个地址赋给一个指针:   
  例十六:   
inta=123,b;   
int*ptr=&a;   
char*str;   
b=(int)ptr;//把指针ptr的值当作一个整数取出来。   
str=(char*)b;//把这个整数的值当作一个地址赋给指针str。 
  现在我们已经知道了,可以把指针的值当作一个整数取出来,也可以把一个整数值当作地址赋给一个指针。   
  指针的安全问题   
看下面的例子:   
  例十七: 
chars= 'a ';   
int*ptr;   
ptr=(int*)&s;   
*ptr=1298;   
  指针ptr是一个int*类型的指针,它指向的类型是int。它指向的地址就是s的首地址。在32位程序中,s占一个字节,int类型占四个字节。最后一条语句不但改变了s所占的一个字节,还把和s相临的高地址方向的三个字节也改变了。这三个字节是干什么的?只有编译程序知道,而写程序的人是不太可能知道的。也许这三个字节里存储了非常重要的数据,也许这三个字节里正好是程序的一条代码,而由于你对指针的马虎应用,这三个字节的值被改变了!这会造成崩溃性的错误。   
  让我们再来看一例:   
  例十八:   
  1、chara;   
  2、int*ptr=&a;   
  ...   
  ...   
  3、ptr++;   
  4、*ptr=115;   
  该例子完全可以通过编译,并能执行。但是看到没有?第3句对指针ptr进行自加1运算后,ptr指向了和整形变量a相邻的高地址方向的一块存储区。这块存储区里是什么?我们不知道。有可能它是一个非常重要的数据,甚至可能是一条代码。而第4句竟然往这片存储区里写入一个数据!这是严重的错误。所以在使用指针时,程序员心里必须非常清楚:我的指针究竟指向了哪里。在用指针访问数组的时候,也要注意不要超出数组的低端和高端界限,否则也会造成类似的错误。   
  在指针的强制类型转换:ptr1=(TYPE*)ptr2中,如果sizeof(ptr2的类型)大于sizeof(ptr1的类型),那么在使用指针ptr1来访问ptr2所指向的存储区时是安全的。如果sizeof(ptr2的类型)小于sizeof(ptr1的类型),那么在使用指针ptr1来访问ptr2所指向的存储区时是不安全的。至于为什么,读者结合例十七来想一想,应该会明白的。


摘录的别人的: 

C语言所有复杂的指针声明,都是由各种声明嵌套构成的。如何解读复杂指针声明呢?右左法则是一个既著名又常用的方法。不过,右左法则其实并不是C标准里面的内容,它是从C标准的声明规定中归纳出来的方法。C标准的声明规则,是用来解决如何创建声明的,而右左法则是用来解决如何辩识一个声明的,两者可以说是相反的。右左法则的英文原文是这样说的: 

The   right-left   rule:   Start   reading   the   declaration   from   the   innermost   parentheses,   go   right,   and   then   go   left.   When   you   encounter   parentheses,   the   direction   should   be   reversed.   Once   everything   in   the   parentheses   has   been   parsed,   jump   out   of   it.   Continue   till   the   whole   declaration   has   been   parsed.   


这段英文的翻译如下: 

右左法则:首先从最里面的圆括号看起,然后往右看,再往左看。每当遇到圆括号时,就应该掉转阅读方向。一旦解析完圆括号里面所有的东西,就跳出圆括号。重复这个过程直到整个声明解析完毕。 

                笔者要对这个法则进行一个小小的修正,应该是从未定义的标识符开始阅读,而不是从括号读起,之所以是未定义的标识符,是因为一个声明里面可能有多个标识符,但未定义的标识符只会有一个。 

                现在通过一些例子来讨论右左法则的应用,先从最简单的开始,逐步加深: 

int   (*func)(int   *p); 

首先找到那个未定义的标识符,就是func,它的外面有一对圆括号,而且左边是一个*号,这说明func是一个指针,然后跳出这个圆括号,先看右边,也是一个圆括号,这说明(*func)是一个函数,而func是一个指向这类函数的指针,就是一个函数指针,这类函数具有int*类型的形参,返回值类型是int。 

int   (*func)(int   *p,   int   (*f)(int*)); 

func被一对括号包含,且左边有一个*号,说明func是一个指针,跳出括号,右边也有个括号,那么func是一个指向函数的指针,这类函数具有int   *和int   (*)(int*)这样的形参,返回值为int类型。再来看一看func的形参int   (*f)(int*),类似前面的解释,f也是一个函数指针,指向的函数具有int*类型的形参,返回值为int。 

int   (*func[5])(int   *p); 

func右边是一个[]运算符,说明func是一个具有5个元素的数组,func的左边有一个*,说明func的元素是指针,要注意这里的*不是修饰func的,而是修饰func[5]的,原因是[]运算符优先级比*高,func先跟[]结合,因此*修饰的是func[5]。跳出这个括号,看右边,也是一对圆括号,说明func数组的元素是函数类型的指针,它所指向的函数具有int*类型的形参,返回值类型为int。 


int   (*(*func)[5])(int   *p); 

func被一个圆括号包含,左边又有一个*,那么func是一个指针,跳出括号,右边是一个[]运算符号,说明func是一个指向数组的指针,现在往左看,左边有一个*号,说明这个数组的元素是指针,再跳出括号,右边又有一个括号,说明这个数组的元素是指向函数的指针。总结一下,就是:func是一个指向数组的指针,这个数组的元素是函数指针,这些指针指向具有int*形参,返回值为int类型的函数。 

int   (*(*func)(int   *p))[5]; 

func是一个函数指针,这类函数具有int*类型的形参,返回值是指向数组的指针,所指向的数组的元素是具有5个int元素的数组。 

要注意有些复杂指针声明是非法的,例如: 

int   func(void)   [5]; 

func是一个返回值为具有5个int元素的数组的函数。但C语言的函数返回值不能为数组,这是因为如果允许函数返回值为数组,那么接收这个数组的内容的东西,也必须是一个数组,但C语言的数组名是一个右值,它不能作为左值来接收另一个数组,因此函数返回值不能为数组。 

int   func[5](void); 

func是一个具有5个元素的数组,这个数组的元素都是函数。这也是非法的,因为数组的元素除了类型必须一样外,每个元素所占用的内存空间也必须相同,显然函数是无法达到这个要求的,即使函数的类型一样,但函数所占用的空间通常是不相同的。 

作为练习,下面列几个复杂指针声明给读者自己来解析,答案放在第十章里。 

int   (*(*func)[5][6])[7][8]; 

int   (*(*(*func)(int   *))[5])(int   *); 

int   (*(*func[7][8][9])(int*))[5]; 

                实际当中,需要声明一个复杂指针时,如果把整个声明写成上面所示的形式,对程序可读性是一大损害。应该用typedef来对声明逐层分解,增强可读性,例如对于声明: 

int   (*(*func)(int   *p))[5]; 

可以这样分解: 

typedef     int   (*PARA)[5]; 
typedef   PARA   (*func)(int   *); 

这样就容易看得多了。
	



 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值