C语言集训---朱鹏圣---第五次集训

173 阅读6分钟

指针

  • 指针就是地址,地址就是指针

  • 地址就是内存单元的编号

  • 指针变量是存放地址的变量

  • 指针和变量是两个不同概念

-指针本质就是一个操作受限的非负整数

1.指针的重要性

  • 表示一些复杂的数据结构

  • 快速的传递数据

  • 使函数返回一个以上的值

  • 能直接访问硬件

  • 能够方便的处理字符串

  • 是理解面向对象语言中引用的基础

总结:指针是C语--言的灵魂(十分重要)

2.指针的定义
  • 地址

    • 内存单元的编号
    • 从零开始的非负整数
    • 范围:4G
3.指针的分类
  • 基本类型指针
#include <stdio.h>

int main (void)
{
    int *p;//p是变量的名字,int *p表示变量存放的是int类型变量的地址
            //int * p;不表示定义了一个名字叫做*p的变量
            //int * p;应该这样理解;p是变量名,p变量的数据类型是int *类型
            // 所谓int *类型实际就是存放int变量地址的类型
    int i = 3int j;

    p = &i;
        /*
        1.p保存了i的地址,因此p指向i
        2.p不是i,i也不是p,更准确的说:修改p的值不影响i的值,修改i的值不影响p
        3.如果一个指针变量指向了某个普通变量,则
            *指针变量    就完全等于    普通变量
            例子:
                    如果p是某个指针变量,并且p存放了普通变量i的地址
                    则p指向了普通变量i
                    * p 就完全等同于  i
                    或者说:在所有出现*p的地方都可以替换成i
                    在所有出现i的地方都可以替换成*p
        /*
    j = *p;
    printf("i = %d,j = %d\n",i,j);
    
    return 0;
}
    

附录: *的含义

1.乘法

2.定义指针变量

1.乘法

2.定义指针定量
  • int p;//定义了一个名字叫p的变量,int表示p只能存放int变量的地址
3.指针运算符
  • 该运算符放在已经定义好的指针变量的前面

  • 如果p是一个已经定义好的指针运算

  • 则*p表示以p的内容为地址的变量

如何通过被调函数修改主调函数的值

  • 1.实参必须为该普通变量的地址

  • 2.形参必须为指针变量

  • 3.在被调函数中通过

形参名=.....

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

指针和数组

  • 指针和一维数组

    • 一维数组名

      • 一维数组名是个指针常量

      • 它存放的是一维数组第一个元素的地址

下标和指针的关系

-如果p是个指针变量,则

p[i]永远等价于*(p+i)

  • 确定一个一维数组需要几个参数【如果一个函数处理一个一级 数组需要两个参数:
1.数组第一个元素地址
2.数组的长度
  • 指针变量不能相加,不能相乘,也不能相除

  • 如果两个指针变量指向的是同一块连续空间中不同的存储单元,则这两个指针变量才可以相减(代码在后面)

    *p q r本身所占的字节数是否一样*
    

* 一个指针变量到底占几个字节*

  • 假设p指向char类型变量(一个字节)
  • 假设q指向int类型变量(四个字节)
  • 假设r指向double类型变量(八个字节) 预备知识: 1.sizeof(数据类型)

功能:返回值就是该数据类型所占的字节数

例子:sizeof(int) = 4

sizeof(char) = 1

sizeof(double) = 8

sizeof(变量名) 功能:返回值是该变量所占的字节数

总结:

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

一个变量的地址使用该变量首字节的地址来表示

  • 指针和二维数组

    • 多级指针:

      • int i = 10;int * p=&i;//p只能存放int类型变量的地址

      • int q = &p;//q是int类型,所谓的int**类型就是指q只能存放int*类型变量的地址

      • int*** r = &q;

      printf(“i = %d\n",***r); 3.指针和函数

4.指针和结构体

5.多级指针

专题:动态内存分配

  • 传统数组的缺点:

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

    例子:

            int a[5];//ok
            int len = 5;int a[len];//error
    
    • 传统形式定义的数组,该数组的内存程序员无法手动释放,数组一旦定义,系统为该数组分配的存储空间就会一直存在,直到该函数运行完毕时,数组的空间才会被系统释放

    • 数组的长度一旦定义,其长度就不能再更改数组的长度,不能在函数运行的过程中动态的扩充或缩小

    • A函数定义的数组,在A函数运行期间可以被其他函数使用,但A函数运行完毕之后,A函数中的数组将无法再被其他函数使用

    *传统方式定义的数组不能跨函数使用

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

答:动态数组很好的解决了传统数组的这四个缺陷

传统数组也叫静态数组

  • 动态内存分配距离-动态数组的构造

  • 静态内存和动态内存的比较

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

  • 跨函数使用内存的问题

代码实操

1.指针经典互换

#include<stdio.h>

void  huhuan(int *p, int *q)

{
   int t;

   t = *p;
   *p = *q;
   *q = t;

   return; 
}

int main(void)
{
    int a = 3;
    int b = 5;

    huhuan(&a,&b);
    printf("a = %d, b = %d\n",a,b);

    return 0;
}

image.png 2.确定数组

#include <stdio.h>

void f(int * pArr,int len)
{
    int i;
    for (i = 0;i<len;i++)
        printf("%d   ", pArr[i]);

    //pArr[i]
    printf("\n");
}

int main(void)
{
    int a[5] = {1,2,3,4,5};
    int b[6] = {-1,-2,-3,4,5,-6};
    int c[100] = {1,99,22,33};

    f(a,5);
    f(b,6);
    f(c,100);

    return 0;
}

image.png 3.指针相减


int main(void)
{
    int i = 5;
    int j = 10;
    int * p = &i;
    int * q = &j;
    int a[5];
    p = &a[1];
    q = &a[4];
    printf ("p和q所指向的单元相隔%d个单元\n",q-p);

    return 0;
}

image.png 4.指针字节问题

#include<stdio.h>

int main(void)
{
    char ch = 'A';
    int i = 99;
    double X = 66.6;
    char * p = &ch;
    int *q = &i;
    double * r = &X;

    printf("%d %d %d\n",sizeof(p),sizeof(r));

    return 0;


}

image.png 5.malloc的使用

malloc 是memory(内存)allocate(分配)的缩写
*/

#include <stdio.h>
#include<malloc.h>

int main(void)
{
    int i = 5;//分配了4个字节,静态分配
    int*p = (int *)malloc(4);
    /*
    1.要使用malloc函数,必须添加malloc.h这个头文件
    2.malloc函数只有一个形参,并且形参是整型
    3.4表示请求系统为本程序分配4个字节
    4.malloc函数只能返回第一个字节的地址
    5.5行分配了8个字节,p变量占4个字节,指向的内存也占着四个字节
    6.p本身
    */
   free(p);//free(p)表示把p所指向内存给释放掉了,p本身的内容是静态的,不能由程序释放
   printf("同志们好!\n");

   return 0;
}

image.png 6.动态一维数组的使用

#include <malloc.h>
int main(void)

{
    int a[5];
    int len;
    int * pArr;
    int i;//动态的构造一维数组

    printf("请输入你要存放的元素的个数:");
    scanf("%d",&len);
    pArr = (int *)malloc(4 * len);//第12行 本行动态构造了一个一维数组

//对一维数组进行操作进行操作
for (i = 0;i < len;++i)
    scanf ("%d",&pArr[i]);

//对一维数组进行输出
printf("一维数组的内容是:");
for (i = 0;i<len;++i)
    printf ("%d\n" , pArr[i]);
   
   
    return 0;
}

习题作业

  1.  8 8
    
     4 4
    
     0 0
    
     2 2
     
    
  2.  4
     
     
    
  3.  &ref
    
     一维数组的第一个元素的地址
    
     指向下一个地址
     
    
  4.  a组:12  16
    
     b组:12  14
    
  5.  a.12 16
    
     b.12  16