C语言集训-郑露平-第五次作业

143 阅读3分钟

指针

一、指针的简单用法:

QQ图片20211202215405.png

二、指针的重要性:

​ 1、表示一些复杂的数据结构

​ 2、快速的传递数据

​ 3、使函数返回一个以上的值

​ 4、能直接访问硬件

​ 5、能够方便的处理字符串

​ 6、是理解面向对象语言中引用的基础

反正就是很重要!

指针的分类:

​ 1、基本类型指针

​ 2、指针和数组

​ 3、指针和函数

​ 4、指针和结构体

​ 5、多级指针

三、指针的定义:

地址:

​ 内存单元的编号

​ 从零开始的非负整数

​ 范围:4G【0——4G-1】

指针:

​ 指针就是地址,地址就是指针,指针变量是存放地址的变量。

四、基本类型指针:

如下:

#include <stdio.h>
int main(void)
{  int * p;//p是变量的名字,int *表示p变量存放的是int类型变量的地址
    int i=3;
    p=&i;
        /*  1、p保存了i的地址,因此p指向i
            2、p不是i,i也不是p,也就是说修改p的值不影响i的值,修改i的值也不影响p的值
            3、如果一个指针变量指向了某个普通变量,则
            *指针变量就完全等同于普通变量,或者说所有出现的i都可以用*p替代,所有出现*p的地方都可以用i替换
            *p就是以p的内容为地址的变量
             */
    return 0;
}
经典指针程序——互换两个数的值、

​ 代码如下:

#include <stdio.h>
void hh(int * p,int * q)
{ int t;
   t=*p;
   *p=*q;
   *q=t;
    return;

}

int main(void)
{    int a=3;
     int b=5;
     hh(&a,&b);
       printf("a=%d b=%d\n",a,b);



    return 0;
}

​ 其中注意定义函数中是用*q *p和t互换,q,p是指针,属于地址;

如何通过被调函数来改变主调函数的值:

​ 1、实参必须为该普通函数的地址

​ 2、形参必须为指针变量

​ 3、在被调函数中通过

​ *形参名=.....

​ 的方式就可以修改主调函数相关变量的值

五、形参与实参:

形参和实参永远是不同的!

六、指针和数组:

1、指针和一维数组:

一维数组名

​ 一维数组名是一个指针常量,它存放的是一维数组第一个元素的地址

如图:

QQ图片20211202215446.png

2、下标与指针的关系:

​ 如果p是个指针变量,则p[i]永远等价于*(p+i)

3、界定一个一维数组需要两个参数的原因:

​ 运行如下代码可知

#include <stdio.h>
void f(int *arr,int len)
{  int i;
    for(i=0;i<len;++i)
       printf("%d ",*(arr+i));
}

int main(void)
{    int a[5]={1,2,3};
     int b[100]={1,2,3,1,2,2};            
           f(a,2);
        f(b,100);

    return 0;
}

​ 界定一个一维数组需要知道数组名和长度

4、指针变量的运算:

​ 指针变量不能相加 不能相乘 也不能相除

​ 如果两个指针变量指向的是同一块连续空间中的不同储存单元,

​ 则这两个指针变量才能相减

5、一个指针变量到底占多少个字节?

一个指针变量,无论它指向的变量占几个字节,该指针变量本身只占四个字节。

七、动态内存分配:

1、 传统数组的缺点:

​ 1、数组长度必须事先制定,且只能是常整数,不能是变量。

​ 例子:

​ int a[5]; //ok

​ int len =5; int a[len]; //error

​ 2、传统形式定义的数组,该数组的内存无法手动释放。

​ 也就是说,在一个函数运行期间,系统为该函数的数组分配的空间会一直存在

​ 3、数组的长度一旦定义,其长度在函数运行过程中就不能被改变

​ 4、A函数定义的数组,在A函数运行期间可以被其他函数使用,但A函数运行完毕之后,

​ A函数中的数组将不能被其他函数使用

2、为什么需要分配动态内存?

​ 动态内存能够解决传统数组的缺陷

3、动态内存分配举例——动态数组的构造

malloc函数的使用:

​ a、要使用malloc函数,必须添加malloc.h这个头文件

​ b、malloc函数只有一个形参,并且形参是整形

​ 例如以下代码

#include <stdio.h>
#include <malloc.h>
void f(int* q)
{
    *q=200;

}
int main(void)
{  int* p=(int*)malloc(sizeof(int));
      *p=10;
   printf("%d\n",*p);
   f(p);
   printf("%d\n",*p);
       
    return 0;
}

动态一维数组的构造

​ 代码如下:

#include <stdio.h>
#include <malloc.h>
int main(void)
{  int* arr;
   int len;
   int i;
   printf("输入你想输入元素的个数");
   scanf("%d",&len);
   arr=(int*)malloc(4*len);
      for(i=0;i<len;++i)
         scanf("%d",&arr[i]);
   printf("数组元素为:\n");
        for(i=0;i<len;++i)
           printf("%d\n",*(arr+i)); 
   

   return 0;
}

​ 此代码能够很好的体现出动态内存分配

4、动态内存与静态内存的比较

​ 静态内存是系统自动分配,由系统自动释放

​ 静态内存是在栈分配

​ 动态内存是由程序员手动分配,手动释放

​ 动态内存是在堆分配

八、多级指针:

静态变量不能跨函数使用详情

​ 此代码

#include <stdio.h>
void f(int** q)
{  int i=10;
   *q=&i;
}
int main(void)
{  int* p;
    f(&p);
    printf("%d\n",*q);   
    return 0;
}

​ 在现在的编译器中运行报错

动态函数跨函数使用详情:

​ 代码如下

#include <stdio.h>
#include <malloc.h>
void f(int** q)
{
    *q=(int*)malloc(sizeof(int));
    **q=5;
}
int main(void)
{   int* p;
     f(&p);
     printf("%d\n",*p);
    return 0;
}

九、课后作业:

​ 1、88 44 00 22

​ 2、4个

​ 3、ref地址是8的储存地址;ref+1是ref指向的地址之后的第一个地址;ref不能自增

​ 4、 12 16;12 14;

​ 5、 12 16;12 14;