C语言第八章:指针

第八章:指针

*:1:标志、乘、指针取内容值

一、指针变量定义

C语言有两种变量:其中变量(普通变量)存储内容值;地址变量(指针变量)存储地址值

  1. 定义的格式:类型名 *指针变量名;

    • 如:int a, b, *p1, *p2;

    • 在定义指针变量时,指针变量名前的“*”表示现定义的是一个指针类型的变量。星号并不是指针变量名的一部分,只有一个标志

    • 指针变量专门用来存地址,禁止将 个整型值直接 一个整型值直接 赋给一个指针量

  2. 指针变量的引用

    1. “&”取地址运算符,通过&运算符可以取出普通变量的地址

    2. “*” 指针运算符,*可以取出指针变量所指向的普通变量的值,(间接引用普通量)

      • 可以通过赋值使一个指针变量“指向”某一普通变量( 指针变量=&普通变量)
      int a=10;
      int *p;
      p=&a;
      
      • 在C语言中正确的做法是先让指针变量指向一个确定的存储单元后,再通过该指针变量引用它所指向的存储单元
      int *p;
      *p=200; /*危险*/
      
      • 变量名(普通变量、指针变量)都表示其存储单元内的值
      p1=p2; /*p1指向了p2 所指向的单元*/
      *P1=*P2 /*读p2的值写给p1*/
      
  3. *的作用

    1. 做乘运算符(双目)

    2. 做标志

    int a=10;
    int *p=&a;
    
    1. 做指针运算符
    int a=10;
    int *p=&a;
    *p=20;
    
  4. 若指针变量p指向变量a,即将变量a的地址赋给了指针变量p

如:int a=20,*p=&a

等价表

A、*p<=>a
B、p<=>&a 
C、&*p〈=〉&a〈=〉p
D、*&a <=> *p a <=> 
E、(*p)++ a++ /*都是给变量a的值加1*/
(*p)-- a--
++(*p) ++a ++*p
--(*p) --a --*p
  1. 所有的指针变量在内存中分配的字节数相同,都为二字节。sizeof()
float *p1;
float *p2;
sizeof(p1) /*2*/
sizeof(p2) /*2*/
  1. 案例:

    • 指针变量声明后需要初始化才能使用
    /*给出一个错误案例*/
    #include<stdio.h> 请输出下列程序的结果
    void swap(int *p1,int *p2)
    {
         int *temp ;
        *temp=*p1;
        *p1=*p2;
        *p2=*temp;}
    main()
    { 
        int a,b;
        int *p1=&a,*p2=&b;
        scanf("%d%d",p1,p2);
        swap(p1,p2); printf("%d,%d",*p1,*p2);
    } 
    
    • 形参用完后会被释放掉
    #include<stdio.h> 请输出下列程序的结果
    void swap(int *p1,int *p2)
    {
        int temp;
        temp=*p1;
        *p1=*p2;
        *p2=temp; 
    }
    main()
    { 
        int a,b;
        int *p1=&a,*p2=&b;
        scanf("%d%d",p1,p2);/*输入5,2*/
        swap(p1,p2); 
        printf("%d,%d",*p1,*p2);/*输出5,2*/
    } 
    

二、一维数组与指针变量

(1) int  fun(int a[10])<=>int fun(int *a  )<=>int fun(int a[  ])

若数组做为形参,则将数组名做指针变量来处理

  1. 指向数组元素的指针变量

由于数组元素与普通一样,所以定义指向数组元素的指针变量
与定义指向普通变量的指针变量完全一一样

如:

int s[10] a b; s[10],a,b;
int b[3][6];
int *p;
p=&a;
p=&s[2]; 
p=&b[2][4];
  1. 指向一维数组的指针变量

    1. 在C语言中规定:数组名代表数组的首地址,而且是一个地址常量,如:int a[10];
      int *p; P=a; <=> P=&a[0];

    2. 当指针变量指向数组中的某一个元素时,指针变量加1后指向数组的下一个元素,指针变量减1时指向数组中前一个元素,如:float a[10]; float *p; p=&a[4]; 则p-3 指向 a[1]

    3. 当指针变量指向数组时,下标运算([ ])用于数组也可用于指针变量后

    int a[N],*p=a;
    p+i<=>a+i<=>&a[i]
    *(p+i)<=>*(a+i)<=>a[i]<=>p[i]
    -------------------------
    *p++<=>*(p++) 
    

    举例指针在数组中的使用:

    main()
    {   int *p,a[3],I;
        p=a;
        for(i=0;i<3;i++)
        scnaf("%d",p++);
        printf("\n\n");
        for(p=&a[0];p<a+3) 
        printf("%d ",*p++);
    }
    
    1. 若两个指针变量指向同一个数组,则这两个指针变量可以进行大小比较
    char s[10];
    char *p1=s+3,*p2=&s[7];
    p1>p2 =>0  p1<p2 =>1
    p1-p2=>-4  p2-p1=>4
    
    1. 在形参中的数组实际上是一个指针变量,并不是真正的数组,因为该“数组名”的值是可以改变的,而真正的数组名的值是不能改变的

    2. 若形参是数组或指针变量,则在函数中可以通过该形参改变实参的值

三、指向多维数组的指针变量

&与*互逆

*与[]等价

&与[]互逆

指向二维数组的指针,先看是列指针还是行指针

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fCYyRfmO-1646233686950)(C:\Users\tengfei\Pictures\Camera%20Roll\2022-02-09_21-03-31.png)]

  1. 指向多维数组元素的指针变量

    如: int a[3][4];

    • a+1是跳过一行。因为二维数组名是行指针,加1是跳过一行不是一个元素

    • 只有列指针才是“真正”指向元素。即指向某一个元素的存储单元

    • 一维数组名表示的是列指针;二维数组名表示的是行指针

    若a是一个二维数组,则有:

    • a+i是行指针,即指向的是一整行。若对它加1则指向下一行

    • *(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]和a[i][j]一样,都表示元素a[i][j]

    1. 如:int a[3][4]; int *p=&a[0][3];

    2. 则:p+1指向元素a[1][0]; p-2指向元素a[0][1]

    3. 常用于取二维数组a元素地址的方式:&a[i][j]、a[i]+j、*(a+i)+j

    main()
    {
    int a[3][3]={1,2,3,4,5,6,7,8,9},*p;
    for(p=a[0];p<a[0]+9;p++) /*a[0]等价于&a[0][0],其中&与[]抵消*/
    printf("%d",*p);
    }
    
2. 指向由m个元素组成的一维数组的指针变量
定义指向由m个元素组成的一维数组的指针变量的格式:基类型 (*指针变量名)[m];
如:`int a[5][7];int (*)[7]; int (*p)[7];p=a;`

```c
main()
{            
  int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}            ;
  int (*p)[4];
  p=a;
    for(i=0;i<3;i++)
    { 
        for(j=0;j<4;j++)
        printf("%d",p[i][j]);
        printf("\n");
    } 
}

四、指向字符串的指针变量

一个字符串就是第一个字符的地址

字符串常量:C语言对字符串常量是按首地址处理字符串常量

1) char str[]="China" /*合法,有双引号做标识可省略花括号*/
2) char *p=“China”;/*合法,字符串就是第一个字符的地址,用P指针来接收*/
3) str="Chinese"; /*不合法,str是个常量,不可更改*/
4) p="Chinese"; /*合法,p改变了它的指向*/
5) char *p={"China"} /*不合法,加了花括号系统不会认为是字符串了,指针变量得地址而不是花括号*/
6) char str[]={"China"} /*合法,有双引号做标识可省略花括号,也可不省略*/

main()
{ 
    char s[20]="abcdefGHI";
    char *p="1234567";
    printf("%s\n",s+2);
    printf("%s\n",p+5);
    printf("%s\n",strcat(s+3,p+4));
    printf("%d\n",strlen(p+2));
    printf("%s\n",strcpy(p+3,s+9));
    printf("%s\n",s);
    scanf("%s",s+3); /*输入:ABC DEF<回车>*/
    printf("%s",s);

五、指向函数的指针变量

函数名与数组名一样,是起始地址,而且是一个地址

定义:类型名 (*指针变量名)(函数参数列表);

类型名是指函数返回值类型

例如:int (*p)(int,int);

类型名 (*指针变量名)(); //定义指向函数的指针变量
类型名 普通变量名; //定义普通变量
类型名 数组名[]; //定义数组
类型名 *指针变量名;//定义指针变量
类型名 函数名( )  //定义函数
{。。。。}
类型名 (*指针变量名)[M]; //定义指向行的指针变量

int min(int a,int b)
{ return a>b?b:a;}
int max(int a,int b)
{ return a>b?a:b ; }
main()
{ int x=6,y=10;
int (*p)(int,int);
p=max;
printf("%d",max(x,y));
printf("%d",p(x,y)); /*等价于printf("%d",(*p)(x,y));*/
p=min;
printf("%d",min(x,y));
printf("%d",p(x,y));
}

注意:

  • 在定义指向函数的指针变量时,要注意有两个小括号必须要有,不需要定义形参

  • 单独的函数名代表该函数的首地址(函数的入口地址)

  • 函数的指针变量只能指向函数的入口处(函数的首地址),不能指向函数中的某条指令。(另对指向函数的指针变量加1是没有意义的)。

  • 给指向函数的指针变量赋值时,只写函数名即可,不必写参数。

六、返回指针的函数

定义:类型名 *函数名(形参列表){}

int *fun(int *x,int *y)
{
 if(*x<*y)
   return x;
else
   return y;
}
main()
{ 
  int a=7,b=8,*p,*q,*r;
  p=&a; q=&b;
  r=fun(p,q);
  printf("%d,%d,%d\n",*p,*q,*r);
}

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

  1. 指针数组

若一个数组的所有元素均为指针类型(地址),则称为指针数组

格式:类型名 *数组名[常量表达式];

例:int *s[10];

它的每个 个 类 元素都是一个指针类型(地址),即它的每个元素都 相当于一个指针变量

main()
{
 char ch[3][4]={"123","456","78"},*p[3];
 int i;
 for(i=0;i<3;i++)
   p[i]=ch[i];
 for(i=0;i<3;i++)
   printf("%s",p[i]);
} 
/*输出:12345678*/
  1. 指向指针的指针变量

用来存放指针变量地址的指针变量称为指向指针的指针变量

格式:基类型名 **指针变量名;

如:

int a=3;
int *p=&a;
int **k=&p;
/*
 *     则:*k得到变量p(变量a的地址)
 *     **k 得到变量a的值(a的数据3
 */

八、空指针

空指针所指向的房子不存在

  • 指针变量可以有空值,即指针变量不指向任何变量,不指向任何有用的存储单元

  • 在系统中已将NULL定义为0,即NULL的值为0

  • 当一个指针变量的值为空指针时,我们不能引用它所指向的存储单元

#include<stdio.h>
main()
{ 
  int a[]={1,2,3,4,5,6,7,8,9,10,11,12};
  int *p=a+5,*q=NULL;
  *q=*(p+5);
  printf("%d %d\n",*p,*q); /*程序报错,*q没有指向任何内存空间,所以无法进行赋值*/
}

如:

int a=3;
int *p=&a;
int **k=&p;
/*
 *     则:*k得到变量p(变量a的地址)
 *     **k 得到变量a的值(a的数据3
 */

八、空指针

空指针所指向的房子不存在

  • 指针变量可以有空值,即指针变量不指向任何变量,不指向任何有用的存储单元

  • 在系统中已将NULL定义为0,即NULL的值为0

  • 当一个指针变量的值为空指针时,我们不能引用它所指向的存储单元

#include<stdio.h>
main()
{ 
  int a[]={1,2,3,4,5,6,7,8,9,10,11,12};
  int *p=a+5,*q=NULL;
  *q=*(p+5);
  printf("%d %d\n",*p,*q); /*程序报错,*q没有指向任何内存空间,所以无法进行赋值*/
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言第八章是关于指针的使用和相关概念的。同学们在学习这一章节时,可以使用思维导图作为学习工具来帮助理解和记忆。 首先,在思维导图的中央,可以写上章节的主题“C语言第八章-指针”。然后将主题分成几个不同的分支。 第一个分支可以是指针的基本概念和定义。在这个分支中,可以列出指针的定义和声明的语法,以及如何通过指针来访问和修改变量的值。此外,还可以介绍指针的运算符,如取址运算符(&)和解引用运算符(*)。 第二个分支可以是指针和数组的关系。在这个分支中,可以讨论指针和数组之间的相似性和差异性,以及如何使用指针来处理数组元素,如指针的算术运算和指针数组。 第三个分支可以是指针和函数的关系。在这个分支中,可以介绍指针和函数之间的关系,如指针作为函数参数的使用以及函数返回指针的情况。 第四个分支可以是指针和动态内存分配的关系。在这个分支中,可以探讨使用指针来动态分配和释放内存的方法,如malloc()和free()函数的使用。 最后,可以在思维导图的边缘加入一些常见的问题和实例,以帮助同学们更好地理解和应用这些概念。同时,也可以在思维导图中添加一些关键的代码示例,以便同学们进行练习和巩固知识。 通过使用思维导图来整理和展示C语言第八章的内容,同学们可以更加清晰地理解和记忆相关概念,提高学习效果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值