首页 > 其他分享 >C语言指针

C语言指针

时间:2024-07-07 17:55:41浏览次数:17  
标签:10 变量 指向 int C语言 数组 指针

主要内容

  1. 地址和指针
  2. 变量的指针和指向变量的指针变量
  3. 数组的指针和指向数组的指针变量
  4. 字符串的指针和指向字符串的指针变量
  5. 函数的指针和指向函数的指针变量★
  6. 返回指针值的函数
  7. 指针数组和指向指针的指针

地址和指针

  1. 在计算机中所有数据都存放在存储器中。
  2. 把主存储器中的一个字节称为一个内存单元,通过内存单元的编号能正确地访问内存单元,内存单元的编号也称为地址
  3. 指针:通常内存单元的地址称为指针
  4. 内存单元存放的数据是存储单元的内容 

变量的指针和指向变量的指针变量

  1. 在C语言中,一种数据类型或数据结构往往占有一组连续的内存单元
  2. 指针是一个数据结构的首地址,它“指向”一个数据结构
  3. 允许用一个变量来存放指针,这种变量称为指针变量
  4. 指针变量的值就是某个数据结构的地址(指针)
  5. 指针是一个地址,是常量
  6. 指针变量可以存放不同的指针值,是变量
  7. 变量的指针就是变量的地址,存放某变量地址的变量称为指向某变量的指针变量
  8. 在程序中用“*”符号表示“指向”。  
  9. 如果已定义i_pointer为指针变量,
  10. 则*i_pointer是i_pointer所指向的变量
             

int i; i=3;

*i_pointer=3;  //都可以给i赋值

定义指针变量

  1. 定义指针变量的一般形式为:              类型说明符  *指针变量名;
  2. 例如:
– int *p1;      //p1 是指向整型变量的指针变量 – float *p2;    //p2 是指向浮点型变量的指针变量 – char *p3;    //p3 是指向字符型变量的指针变量

指针变量的引用

两个与指针使用有关的运算符: ( 1 ) &:取地址运算符。 – 例如, &a 取得变量 a 的地址。 ( 2 )*:指针运算符(或称“间接访问”运算符)取得指针变量指向的内容。 – 例如 *p取得指针变量p所指向的变量的值。 给指针变量赋值可以有两种方法: ( 1 )定义的同时赋值,如: – int a;        – int *p=&a;   // 定义时初始化,取得 a 的地址赋给指针变量 p ( 2 )定义后赋值,如: – int a; – int *p; – p=&a;   // 取得变量 a 的地址赋给指针变量 p 指针变量中只能存放地址(指针),不要将一个整数(或任何其他非地址类型的数据)赋给一个指针变量

以下的赋值是不合法的:

int *p;

p=100;   // p为指针变量,100为整数,不合法  

//【例10. 1】指针变量的使用。
1    #include <stdio.h>
2    void main()
3    {   int a,b;
4        int *pointer_1, *pointer_2;    //定义指针变量
5        a=100;b=10;
6        pointer_1=&a;   //指针变量pointer_1指向a
7        pointer_2=&b;  //指针变量pointer_2指向b
8        printf("%d,%d\n",a,b);
  printf("%d,%d\n",*pointer_1, *pointer_2);    
  //通过指针变量取得变量的值
10    }

                           

如果已执行了语句“ pointer_1=&a ;”,那么有以下说法: ( 1 ) pointer_1 ó &a ( 2 )* &a ó *pointer_1 ó a ( 3 ) &*pointer_1 ó &(*pointer_1) ó pointer_1 ó &a “&”和“*”运算符的优先级相同,它们按自右至左结合 ( 4 ) (*pointer_1)++ ó a++ ( 5 )* pointer_1++ ó *(pointer_1++) 因为“ ++” 和“ *” 为同一优先级,而结合方向为自右至左
//【例10. 2】输入整数a和b,按从大到小的顺序输出a和b。
#include <stdio.h>
void main()
{    int *p1,*p2,*p,a,b;
    printf("请输入两个整数:");
    scanf("%d,%d",&a,&b);
    p1=&a;p2=&b;  //指针变量指向变量
    if(a<b)
    {    p=p1;p1=p2;p2=p;} 
//指针变量交换指向
    printf("%d,%d\n",a, b);
    printf("%d,%d\n",*p1, *p2);
} 

               

指针变量作为函数参数

  1. 函数的参数也可以是指针
  2. 它的作用是将一个变量的地址传送到函数中
//【例10. 3】编写用指针变量作参数的函数,将输入的两个整数按从大到小顺序输出
#include <stdio.h>
void swap(int *p1,int *p2)  //指针变量作形参
{    int temp;
    temp=*p1;   //交换p1和p2指向的变量的值
    *p1=*p2;    *p2=temp;
}
void main()
{    int a,b;
    int *pointer_1,*pointer_2;
    printf("请输入两个整数:");
    scanf("%d,%d",&a,&b);
    pointer_1=&a;pointer_2=&b;
    if(a<b) 
        swap(pointer_1,pointer_2);  //指针变量作实参,也可以使用swap(&a,&b);
    printf("%d,%d\n",a,b);
}

//【例10. 4】改变形参指针变量的指向,而实参变量不变。
#include <stdio.h>
void swap(int *p1,int *p2)
{  int *p;
    p=p1;   //改变形参指针变量的指向
    p1=p2;    p2=p;
}
void main()
{    int a,b;
    int *pointer_1,*pointer_2;
    printf("请输入两个整数:");
    scanf("%d,%d",&a,&b);
    pointer_1=&a;pointer_2=&b;
    if(a<b) 
        swap(pointer_1,pointer_2);  //指针变量作实参
    printf("%d,%d\n",*pointer_1,*pointer_2);  //实参指针变量的指向不变
}

在swap函数中交换形参p1和p2的值,不能交换实参pointer_1和pointer_2的值

//【例10. 5】指针变量作参数可以返回多个变化的值。
#include <stdio.h>
void swap(int *p1,int *p2)
{    *p1=100;   //改变形参指针变量的指向
    *p2=200;
}
void main()
{    int a,b;
    int *pointer_1,*pointer_2;
    printf("请输入两个整数:");
    scanf("%d,%d",&a,&b);
    pointer_1=&a;pointer_2=&b;
    if(a<b) 
        swap(pointer_1,pointer_2);  //指针变量作实参,也可以使用swap(&a,&b);
    printf("%d,%d\n",a,b);
}

函数的调用只能得到一个返回值(函数值)

而用指针变量作参数可以返回多个结果

数组的指针和指向数组的指针变量

  1. 数组的指针就是指数组的首地址,数组元素的指针是指数组元素的地址。
  2. 定义一个指向数组元素的指针变量的方法,与定义指针变量的方法相同 

int a[10]; //定义a为包含10个整型元素的数组

int *p;   //定义p为指向整型变量的指针

p=&a[0];  //p指向数组的第0个元素a[0]

   

数组的指针

  1. C语言规定,数组名代表数组的首地址,也就是第0号元素的地址

p=&a[0] ; 等价于   p=a ;

int *p=&a[0] ;     等价于    int *p=a;   等价于  int *p; p=&a[0];

通过指针引用数组元素

  1. 如果指针变量p已指向数组中的一个元素,则p+1指向同一数组的下一个元素
  2. 如果p的初值为&a[0],那么:
  3. ó表示等价于

(1)p+i ó a+i ó &a[i]

(2)*(p+i) ó *(a+i) ó a[i]

         如,*(p+5) ó *(a+5) ó a[5]

(3)指向数组的指针变量也可带下标

         p[i] ó *(p+i) ó a[i] ó *(a+i)。

(4)p++ ó p=p+1,

        使得指针变量p指向数组的下一个元素  

• 如果 p=a ,引用数组元素可以有两种方法: – ( 1 ) 下标法 ,采用 a[i] 、 p[i] 的形式访问数组元素 – ( 2 ) 指针法 ,采用 *(a+i)或*(p+i)形式 ,用指针方法访问数组元素。
//【例10. 6】输出数组的全部元素。
(1)使用下标法引用数组元素:
#include <stdio.h>
void main()
{  int a[10],i;
   for(i=0;i<10;i++)
     a[i]=i;  //下标法引用数组元素
   for(i=0;i<10;i++)
     printf("%4d",a[i]);  //下标法引用数组元素
   printf("\n");
}

(2)使用指针法,利用数组名计算地址引用数组元素,编写程序如下:

#include <stdio.h>

void main()

{    int a[10],i;

    for(i=0;i<10;i++)

        *(a+i)=i;   //指针法,利用数组名引用数组元素

    for(i=0;i<10;i++)

        printf("%4d",*(a+i));  //指针法,利用数组名引用数组元素

    printf("\n");

}

(3)使用指针变量指向数组元素,编写程序如下:

#include <stdio.h>

void main()

{    int a[10],i,*p;

    p=a;

    for(i=0;i<10;i++)

        *(p+i)=i;  //指针变量取得数组元素

    for(i=0;i<10;i++)

        printf("%4d",*(p+i));  //指针变量取得数组元素

    printf("\n");

}
( 1 )指针变量中的值可以改变。

p++  ó  p=p+1 //使得指针变量指向下一个数组元素

(2) a 是数组名,它是数组的首地址,是常量

a++   //错误

通过指针引用数组

【例10. 7】输入并输出数组的全部元素。

编写程序如下:

#include <stdio.h>

void main()

{    int *p,i,a[10];

    p=a;

    printf("请输入10个元素:");

    for(i=0;i<10;i++)

        scanf("%d",p++);

    for(i=0;i<10;i++)

      printf("%4d",*p++);

    printf("\n");

}

第一个循环结束后,指针变量p指到数组以后的内存单元,系统并不认为非法。

第二个循环输出的数据为数组以后的内存中的数据。因此为乱码

程序修改如下:

#include <stdio.h>

void main()

{    int *p,i,a[10];

    p=a;

    printf("请输入10个元素:");

    for(i=0;i<10;i++)

        scanf("%d",p++);

    p=a;   //p重新指向a[0]

    for(i=0;i<10;i++)

      printf("%4d",*p++);

    printf("\n");

}

说明:

(1)*p++ 等价于 *(p++)

由于++和*同优先级,结合方向自右而左。

先取得*p的值,后使得p指向下一个元素。

(2)*++p 等价于 *(++p)

先使得p指向下一个元素,后取得*p的值。

(3)(*p)++    表示p所指向的元素值加1。

(4)若p的初值为a,那么:

          *(p++) 等价于 a[0]

          *(++p) 等价于 a[1]

          (*p)++ 等价于 a[0]++

(5)若p指向a数组中的第i个元素,那么:

          *(p--) 等价于 a[i--]

          *(++p) 等价于 a[++i]

          *(--p) 等价于 a[--i]

数组作函数参数

• 数组名可以作为函数的实参和形参
void main()

{    int array[10];

    ……

    ……

    f(array,10);  //数组名作为函数的实参

    ……

}

void f(int arr[],int n)  //数组作为函数形参

{    ……

}

(1)将实参数组array为的首地址传递给形参数组arr ,形参数组和实参数组共用同一段内存

(2)数组形式:

     void f(int arr[],int n)

在编译时也将arr按指针变量处理,相当于:

     void f(int *arr,int n)

数组的指针变量作函数参数

•数组指针变量也可以作为函数的参数使用

【例10. 8】将数组a中的n个整数按相反顺序存放。

分析:

(1)a[0]与a[n-1]交换,a[1]与a[n-2]交换…,直到a[(n-1/2)]与a[n-int((n-1)/2)]交换

(2)设变量i和j,i的初值为0,j的初值为n-1。

(3)将a[i]与a[j]交换,然后使i的值加1,j的值减1,再将a[i]与a[j]交换,直到i≥j

#include <stdio.h>

//数组x作为函数的形参

void inv(int x[],int n)

{    int temp,i,j=n-1;

    for(i=0;i<j;i++,j--)

    {    temp=x[i];

         x[i]=x[j];

         x[j]=temp;

    }  //交换对应元素

}

void main()

{    int i,a[10]={3,7,9,11,0,6,7,5,4,2};

    printf("The original array:\n");

    for(i=0;i<10;i++)

        printf("%4d",a[i]);

    printf("\n");

    inv(a,10);        //数组名作为函数的实参

    printf("The array has benn inverted:\n");

    for(i=0;i<10;i++)

        printf("%4d",a[i]);

    printf("\n");

}

用数组作为函数的形参和实参

#include <stdio.h>

 //指针变量x作为函数的形参

void inv(int *x,int n)

{    int temp,*i,*j;

    i=x;   j=x+n-1;

    for(;i<j;i++,j--)

    {    temp=*i;

         *i=*j;

         *j=temp;

    }    //交换对应元素

}

void main()

{    int i,a[10]={3,7,9,11,0,6,7,5,4,2};

    printf("The original array:\n");

    for(i=0;i<10;i++)

        printf("%4d",a[i]);

    printf("\n");

    inv(a,10);    //数组名作为函数的实参

    printf("The array has benn inverted:\n");

    for(i=0;i<10;i++)

        printf("%4d",a[i]);

    printf("\n");

}

用指针变量作为函数的形参,数组名作为函数调用的实参

实参与形参对应关系的四种形式

实参为指针变量

#include <stdio.h>

//实参是指针变量,

//采用下标法引用数组元素

void inv(int *x,int n)

{    int temp,i,j=n-1;

    for(i=0;i<j;i++,j--)

    { temp=x[i];x[i]=x[j];x[j]=temp; } 

//交换对应元素

}

void main()

{    int i,arr[10]={3,7,9,11,0,6,7,5,4,2},*p;

    p=arr;

    printf("The original array:\n");

    for(i=0;i<10;i++,p++)

        printf("%4d",*p);

    printf("\n");

    p=arr;    //指针变量指向数组的a[0]

    inv(p,10); 

//指针变量作为实参,也可以写为inv(a,10);

    printf("The array has benn inverted:\n");

    for(p=arr;p<arr+10;p++)

        printf("%4d",*p);

    printf("\n");

}

【例10. 9】用选择法对10个整数由大到小排序。

#include <stdio.h>

void sort(int *x,int n) 

//也可以写为 void 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;}

    }

}

void main()

{    int *p,i,a[10]={3,7,9,11,0,6,7,5,4,2};

    printf("The original array:\n");

    for(i=0;i<10;i++)

        printf("%4d",a[i]);

    printf("\n");

    p=a;    //指针变量指向数组的a[0]

    sort(p,10);    //指针变量作为函数实参,也可以写为sort(a,10);

    printf("The array has benn sorted:\n");

    for(p=a,i=0;i<10;i++)

    {    printf("%4d",*p);p++;}

    printf("\n");

}

指向多维数组的指针和指针变量

  1. 多维数组元素的地址
  2. 设有整型二维数组定义如下:            int a[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};
  3. 假设数组a的首地址为1000 ,如图。

指向多维数组的指针

  1. 可以把一个二维数组分解为多个一维数组
  2. 分解为三个一维数组,即a[0]、a[1]和a[2]。每一个一维数组包含有四个元素。
一维数组 a[0] ,包含 a[0][0] 、 a[0][1] 、 a[0][2] 和 a[0][3]

                          

  1. 从二维数组的角度来看:
  2. a是二维数组名,代表整个二维数组的首地址,也就是二维数组第0行的首地址,为1000
  3. a+1代表第一行的首地址,为1016

(2)a[0]是第0行一维数组的数组名和首地址,值为1000。

–       * (a+0)     ó       *a        ó      a[0]  ó  &a[0][0]

(3)a+1是二维数组第1行的首地址,其值为1016

– a[1] 是第 1 行一维数组的数组名和首地址,其值也为 1016 。 –      a[1]     ó    *(a+1)      ó      &a[1][0]

(4)可得出:

•       * (a+i)    ó    a[i]     ó     &a[i][0]

(5)a[0] ó a[0]+0,是一维数组a[0]的第0号元素的首地址

a[0]+1则是a[0]第1号元素的首地址,a[0]+2是a[0]第2号元素的首地址

可以得出:

– a[i]+j 是一维数组 a[i] 的第 j 号元素的首地址 – a[i]+j  ó &a[i][j]

(6)a[i]  ó  *(a+i),a[i]+j   ó  *(a+i)+j

*(a+i)+j是二维数组a第i行第j列元素的首地址,

*(*(a+i)+j) ó *(a[i]+j)    ó   a[i][j]

【例10. 10】输出二维数组的有关值。

#include <stdio.h>

void main()

{   int a[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};

   printf("%d,%d\n",a, a+1);

   printf("%d,%d,%d,%d\n", a[0], *a, *(a+0), &a[0][0]);

   printf("%d,%d,%d\n", a[1], *(a+1), &a[1][0]);

   printf("%d,%d\n",a[1],*(a+1));

   printf("%d,%d,%d\n", a[1]+0, a[1]+1, a[1]+2);

   printf("%d,%d,%d\n", *(a+1)+0, *(a+1)+1, *(a+1)+2);

   printf("%d,%d,%d\n", *(a[1]+0), *(a[1]+1), *(a[1]+2));

   printf("%d,%d,%d\n", *(*(a+1)+0), *(*(a+1)+1), *(*(a+1)+2));

}

指向多维数组的指针变量

  1. 指向二维数组指针变量定义的一般形式为:
  2. 类型说明符  (*指针变量名)[长度];
  3. 类型说明符:为所指向数组的数据类型
  4. *:表示变量是指针变量
  5. [长度]:表示一维数组的长度,也就是二维数组的列数             –int (*p)[4];
  6. p是一个指针变量,指向包含4个元素的一维数组。

【例10. 11】利用指向数组的指针变量,按行列方式输出二维数组。

#include <stdio.h>

void main()

{   int a[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};

   int (*p)[4];

   int i,j;

   p=a;   //指针指向而为数组的第0行

   for(i=0;i<3;i++)

   {   for(j=0;j<4;j++)

         printf("%4d",*(*(p+i)+j)); 

//*(*(p+i)+j) 相当于p[i][j],相当于 *(*(a+i)+j),相当于 a[i][j]

      printf("\n");

   }

}

字符串的指针和指针变量

可以用两种方法访问一个字符串 : (1 )用字符数组存放和处理字符串

【例10. 12】定义并初始化一个字符数组,然后输出字符串。

#include <stdio.h>

void main()

{   char string[]="I love China!";

   printf("%s\n",string);

}

string是数组名,它表示字符数组的首地址

(2)用字符指针指向一个字符串。

 通过定义字符指针变量指向字符串中的字符 

【例10. 13】定义指向一个字符串的字符指针变量。

#include <stdio.h>

void main()

{  char *string=”I love China!”;

  printf("%s\n",string);

}
• 在程序中定义了一个字符指针变量 string ,用字符串常量“ I love China !”初始化 • 实际是把字符串第 0 个元素的地址赋给指针变量 string

char *string=”I love China!”;

• 指向字符串的指针变量的定义,赋给指针变量地址例如: •         char c,*p=&c; • 表示 p 是一个指向字符变量 c 的指针变量

【例10. 14】输出字符串中第n个字符后的所有字符。

#include <stdio.h>

void main()

{   char *ps="This is a book.";

   int n=10;

   ps=ps+n; //ps指向第n个字符

   printf("%s\n",ps);

}

【例10. 15】用指针变量的方法,求字符串的长度。

#include <stdio.h>

void main()

{   char *ps,str[100];

   int n;

   printf("Input a string:\n");

   gets(str);

   ps=str;

   while(*ps!='\0')

      ps++;  //指针变量指向下一个字符

   n=ps-str;

   printf("The length is %d \n",n);

}

字符串指针作函数参数

• 可以用字符数组名或者指向字符串的指针变量作函数参数 , 将字符串的地址从一个函数传递给另一个函数。 • 在被调用函数中改变字符串的内容,也就改变了主调函数中的字符串

【例10. 16】用字符串指针作函数参数,实现字符串的复制。

#include <stdio.h>

void cpystr(char *pss,char *pds) //字符指针变量做函数形参

{   while((*pds=*pss)!='\0')

   {   pds++;pss++;   }

}

void main()

{   char *pa="CHINA",b[10],*pb;

   pb=b;

   cpystr(pa,pb);

//字符串指针变量做函数实参,也可以写为cpystr(pa,b)

   printf("string a=%s\nstring b=%s\n",pa,pb);

}

虽然函数参数传递是单向值传递,但是由于传递的指针变量的值(即地址),所以pss和pa指向同一字符串,pds和pb指向同一字符串。

• ( 5 )可以把指针的移动和赋值合并在一个语句中, cpystr 函数简化为: •      void cpystr(char *pss,char *pds) •       {   while((*pds++=*pss++)!='\0');} • ( 6 ) '\0' 的 ASCⅡ 码值为 0 , while 表达式非 0 就循环,为 0 则结束循环,因此也可省略“ != '\0'” 。简化为 •      void cpystr(char *pss,char *pds) •       {   while (*pdss++=*pss++);   } • 函数参数可以是字符串数组名,也可以是字符指针变量。有以下几种情况: • ①实参和形参均为数组 • ②实参和形参均为字符指针变量 • ③实参为数组名,形参为字符指针变量 • ④实参为字符指针变量,形参为数组

字符指针变量和字符数组的讨论

字符数组和字符指针变量的区别:

(1)字符指针变量是变量,用于存放字符串的首地址,而字符串本身是存放在以该地址为首的一块连续内存空间中。

字符数组由若干个数组元素组成的,每个元素中存放一个字符,整个数组可以存放一个字符串,数组名是字符串的首地址,是常量

• ( 2 )对字符指针变量赋初值: •      char *ps="C Language";      // 合法 • 也可以写为: •      char *ps; •       ps="C Language";   // 合法 • 而对字符数组赋初值: •      char str[20]={"C Language"};   // 合法 • 不能写为: •      char str[20]; •       str={"C Language"};   // 不合法 • 因为数组名是一个常量,不能给常量赋值 • ( 3 )当一个指针变量在未取得确定地址前使用是很危险的。因为指针变量的默认值指向的内存不一定是本程序的存储空间。随意修改容易引起错误。例如: •      char *ps; •       scanf("%s", ps);   // 可能引起错误 • 可以改为: –     char *ps, str[20]; •       ps=str; •       scanf("%s", ps);

函数的指针和指向函数的指针变量★

  1. C语言中,一个函数总是占用一段连续的内存空间,而函数名就是函数所占内存区的首地址
  2. 函数的首地址(或称入口地址)称为函数的指针
  3. 把函数的指针赋予一个指针变量,使该指针变量指向该函数 ,即指向函数的指针变量
  4. 指向函数的指针变量定义的一般形式为:         –类型说明符  (*指针变量名)(函数参数表列);
  5. 类型说明符:表示被指向函数的返回值类型
  6. *:表示后面定义的变量是指针变量
  7. 小括号:表示指针变量所指的是函数。
  8. “(*指针变量名)”两边的括号不能少,否则就成了指针函数 
  9. 函数参数表列只写出各个形式参数的类型即可,也可以与函数原型的写法相同。例如:                      int (*pf)(int,int);
  10. pf是一个指向返回值类型为int的函数的指针变量,并带有两个int类形参数

用函数指针变量调用函数

  1. 可以通过函数名调用函数,也可以通过函数指针变量调用函数。形式为:                                         (*指针变量名) (实参表)

【例10. 17】编写函数求两个形参中较大值。用函数指针变量调用函数。

#include <stdio.h>

int max(int x,int y)

{   if(x>y)return x;

   else return y;

}

void main()

{   int a,b,c;

   int (*pmax)(int,int);  //定义指向int类型函数的指针变量pmax

   pmax=max;   //指针变量指向函数max

   printf("Input two numbers:\n");

   scanf("%d,%d",&a,&b);

   c=(*pmax)(a,b);  //通过指针变量调用函数

   printf("max=%d\n",c);

}

用指向函数的指针作函数参数

  1. 函数的参数可以是指向函数的指针
  2. 用指向函数的指针作函数参数,传递的是函数的地址
  3. 若要在每次调用函数时完成不同操作,可以用指向函数的指针作为函数的参数。
  4. 每次调用时,使该指针指向不同的函数即可

【例10. 18】设一个函数f,在每次调用时可以实现不同功能:第一次调用,求两个数中较大者;第二次调用,求两个数中较小者;第三次调用,求两个数的和。

#include <stdio.h>

int max(int x,int y)  //求最大

{   if(x>y)   return x;

   else   return y;

}

int min(int x,int y)  //求最小

{   if(x<y)   return x;

   else      return y;

}

int sum(int x,int y)  //求最和

{   return x+y;

}

void f(int x,int y,int (*p)(int,int))

{   int result;

   result=(*p)(x,y);   //调用p指向的函数

   printf("%d\n",result);

}

void main()

{   int a,b;

   printf("Input two numbers:\n");

   scanf("%d,%d",&a,&b);

   printf("max=");

   f(a,b,max);  //max函数的入口地址传给形参指针变量

   printf("min=");

   f(a,b,min);  //min函数的入口地址传给形参指针变量

   printf("sum=");

   f(a,b,sum);  //sum函数的入口地址传给形参指针变量

}

返回指针值的函数

• 一个函数可以返回一个整型值、实型值、字符值等,也可以返回一个指针值 ( 即地址 ) • 返回指针值的函数也称为指针型函数

函数名之前加“*”号表明这是一个指针型函数,即返回值是一个指向类型说明符数据类型的指针

【例10. 19】输入一个1~7之间的整数,输出对应的星期名。通过调用指针函数实现。

#include <stdio.h>

char name[8][20]={"Illegal day", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};

char *day_name(int n)  //函数返回值为指向字符的指针

{   if (n<1||n>7)

      return name[0];      //返回第0行第0列字符的地址

   else

      return name[n];      //返回第n行第0列字符的地址

}

void main()

{   int i;

   char *ps;

   printf("Input Day No:\n");

   scanf("%d",&i);

   ps=day_name(i);  //函数返回值为指向第i行的第0个字符的地址

   printf("%s\n",ps);

}

(1)特别注意函数指针变量和指针型函数的区别。“int(*p)()”和“int *p()”完全不同  

– int (*p)() :是一个变量定义, p 是一个指向返回值为 int 类型的函数的指针变量。 – int *p() :是一个函数说明, p 是一个指针型函数,其返回值是一个指向 int 类型数据的指针。

指针数组和指向指针的指针

  1. 指针数组和指向指针的指针变量能够存储另一个指针变量的地址的变量
  2. 指针数组:一个元素都为指针类型的数
  3. 指针数组的每一个元素相当于一个指针变量
– 类型说明符 *数组名 [ 数组长度 ] – int *pa[3];

指针数组

int a[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};

int *pa[3]={a[0],a[1],a[2]};

【例10. 20】利用指针数组输出二维数组。

#include <stdio.h>

void main()

{   int a[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};

   int *pa[3];

   int i,j;

   for(i=0;i<3;i++)

      pa[i]=a[i];  //pa[i]指向一维数组a[i][0]

   for(i=0;i<3;i++)

   {   for(j=0;j<4;j++)

      printf("%4d",*(*(pa+i)+j));  // *(*(pa+i)+j) ó p[i][j] ó a[i][j]

      printf("\n");

   }

}

区别

• 指针数组和二维数组指针变量的区别 – 二维数组指针变量是单个变量, int (*p)[3]; – p 表示一个指向二维数组的指针变量二维数组的列数为 3 – 指针数组表示多个指针元素的数组 , int *p[3]; – p 表示一个指针数组,三个元素 p[0] 、 p[1] 、 p[2] 均为指针变量。

【例10. 21】用指针数组改写【例10. 19】的程序。

#include <stdio.h>

char *day_name(char *name[],int n)  //指针数组作为函数形参

{   char *pa1,*pa2;

   pa1=*name;

   pa2=*(name+n);

   return (n<1||n>7)? pa1:pa2;

}

void main()

{   static char *name[]={"Illegal day", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};   //name数组的每个元素指向一个字符串

   char *ps;

   int i;

   printf("Input Day No:\n");

   scanf("%d",&i);

   ps=day_name(name,i);  //指针数组作函数实参

   printf("%s\n",ps);

}

【例10. 22】将5个国名按字母顺序排列后输出。

#include <stdio.h>

#include <string.h>

void sort(char *name[],int n)  //选择法排序

{    char *pt;

    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)

        {    pt=name[i];name[i]=name[k];name[k]=pt;    }//交换数组元素的指向

  }

}

void print(char *name[],int n)  //打印字符串

{    int i;

    for(i=0;i<n;i++)

        printf("%s\n",name[i]);

}

void main()

{    static char *name[]={"China","America","France","German","Australia"};

    int n=5;

    sort(name,n);  //调用排序函数

    print(name,n);

}

指向指针的指针

• 如果一个指针变量存放的是另一个指针变量的地址,则称这个指针变量为指向指针的指针变量,简称为指向指针的指针 • 定义指向指针的指针变量的一般形式为: •       类型说明符  **指针变量名 ; – ** :表示指向指针的指针, – 类型说明符:表示指针变量所指的指针变量指向的数据类型。 – char **p; • ( 1 ) char **p;   ó   char *(*p); • p 是指向一个字符指针变量的指针变量。 • ( 2 )** p ó *(*p) • *p 取得 p 指向的指针变量 • * (*p) 取得 p 指向的指针变量指向的变量的值。

【例10. 23】用指向指针的指针输出一维数组。

#include <stdio.h>

void main()

{    int a[5]={1,3,5,7,9};

    int *num[5]={&a[0], &a[1], &a[2], &a[3], &a[4]};

//每个元素是一个指针

    int **p,i;

    p=num;    //p指向num数组的第0个元素

    for(i=0;i<5;i++)

    {    printf("%4d",**p); //**p取得变量的值

        p++;    //p指向num数组的下一个元素

    }

    printf("\n");

}
**p :输出数组 a 中的元素。    * p ó num[i] ó &a[i]      ** p ó *&a[i]  ó a[i]

指针数组

【例10. 24】用指向指针的指针输出若干字符串。

#include <stdio.h>

void main()

{   char *name[]={"Basic","Visual Basic","C","Visual C++","Pascal","Delphi"};

   char **p;

   int i;

   for(i=0;i<6;i++)

   {   p=name+i;  //  p ó &name[i]

      printf("%s\n",*p);   // *p ó name[i]

   }

}

程序也可以改写为:

#include <stdio.h>

void main()

{    char *name[]={"Basic","Visual Basic","C","Visual C++","Pascal","Delphi"};

    char **p;

    int i;

    p=name;  //p指向num数组的第0个元素

    for(i=0;i<6;i++)

    {    printf("%s\n",*p);

        p++;  //p指向name数组的下一个元素

    }

}

指针数组作main函数的形参

  1. main函数一般不带参数
  2. 实际上,main函数也可以带参数(形参)
  3. main只能有两个参数,经常命名为argc和argv
– argc (第一个)必须是整型变量 – argv (第二个)必须是指向字符串的指针数组
  • main函数头可写为:
– void main (int argc,char *argv[])
  • main函数是由操作系统调用,所以main函数的参数值从操作系统命令行获得
  • 把实参传送到main函数的形参中。
  • 命令行的一般形式为:
  • 命令名 参数1 参数2 …… 参数n
  • argc:获得命令行中参数的个数
  • argv(指针数组):每一个元素指向命令行中的一个字符串
  • file1 Beijing Tianjin Shanghai Chongqing

【例10. 25】输出命令行的参数。该程序文件名为eg1025.c。

#include <stdio.h>

void main(int argc,char *argv[])

{ while(  argc-->1)

    printf("%s\n",   *++argv);

}

【例10. 26】编写实现echo命令的程序,文件名为echo.c。

许多操作系统提供的echo命令的作用是实现“参数回送”,

将echo后面的各参数(字符串)在同一行上输出。

编写程序如下:

#include <stdio.h>

void main(int argc,char *argv[])

{  while(--argc>0)

  printf("%s%c",  *++argv,(argc>1)?' ':'\n');

}

标签:10,变量,指向,int,C语言,数组,指针
From: https://blog.csdn.net/m0_64148419/article/details/140225274

相关文章

  • C语言下结构体、共用体、枚举类型的讲解
    主要内容结构体结构体数组结构体指针包含结构体的结构链表链表相关操作共用体枚举类型结构体结构体的类型的概念         结构体实现步骤结构体变量的声明structstruct 结构体名{                     ......
  • C语言下的文件详解
    主要内容文件概述文件指针文件的打开与关闭文件的读写文件    把输入和输出的数据以文件的形式保存在计算机的外存储器上,可以确保数据能随时使用,避免反复输入和读取数据 文件概述文件是指一组相关数据的有序集合文件是存储数据的基本单位,可以通过读取文件访问数......
  • C语言大师之路:从零到王者/新手入门(3)选择语句
    序(一些闲话)我希望我的语言不要像专业书那样让人眼花缭乱,所以当我解释语法时,我会尽量避免使用太多专业术语,让说明更容易理解。我会用通俗易懂的语言来解释,而不是像专业书籍那样让人感到困惑。本人计划通过文章分享C语言的核心知识点和学习心得。鉴于仍处于学习阶段,文章中可......
  • C语言大师之路:从零到王者/新手入门(2)变量与运算符
    序(一些闲话)我希望我的语言不要像专业书那样让人眼花缭乱,所以当我解释语法时,我会尽量避免使用太多专业术语,让说明更容易理解。我会用通俗易懂的语言来解释,而不是像专业书籍那样让人感到困惑。本人计划通过文章分享C语言的核心知识点和学习心得。鉴于仍处于学习阶段,文章中可......
  • 【C语言】常用库介绍
    在上一篇博文中,我们讲了C语言的知识点,感兴趣的小伙伴可以自行阅读:一文学完C语言【完整版】在本篇博文中,我们将会介绍C语言一些常用的库和系统函数。stdio.hstdio.h是C语言的标准I/O库,用于读取和写入文件,也用于控制台的输入和输出。标准I/O函数以下函数用于控制台......
  • Go语言--复合类型之指针与数组
    分类指针指针是一个代表着某个内存地址的值。这个内存地址往往是在内存中存储的另一个变量的值的起始位置。Go语言对指针的支持介于Java语言和C/C++语言之间,它既没有想Java语言那样取消了代码对指针的直接操作的能力,也避免了C/C++语言中由于对指针的滥用而造成......
  • 【LeetCode 0141】【链表】【双指针之快慢指针】判断给定单链表是否存在环
    LinkedListCycleGivenhead,theheadofalinkedlist,determineifthelinkedlisthasacycleinit.Thereisacycleinalinkedlistifthereissomenodeinthelistthatcanbereachedagainbycontinuouslyfollowingthe next pointer.Internal......
  • C语言 找出 1000 以内的所有完数
    一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如6的因子为1,2,3,而6=1+2+3,因此6是“完数”,编程序找出1000以内的所有完数,并按下面格式输出其因子:6itsfactorsare1,2,3这个程序找出1000以内的所有完数,并输出每个完数及其因子。(如果因子和等于该数,则该数为完数。)#i......
  • C语言 会员卡计费系统
    设计一个会员卡计费管理系统。功能要求:(1)新会员登记。(将会员个人信息及此会员的会员卡信息进行录入。)(2)会员信息修改。(3)会员续费。(会员出示会员卡后,管理人员根据卡号查找到该会员的信息并显示。此时可以进行续费,续费后,提示成功,并显示更新后的信息。)(4)会员消费结......
  • DAY 1: C语言异或(^)以及按位与(&)的用法
    1.异或(^)的定义        在C语言中,异或操作符是^。异或操作符用于对两个操作数执行按位异或运算,即只有在两个操作数对应位不同时,结果为1。即相同为0不同为1。2.重要结论    1.任何一个数,假定为a,0^a等于a(不进位计算求和),a^a等于0。        2.异或运......