初始指针

初始指针

what is 指针

  1. 指针描述了数据在内存中的位置
  2. 指针也就是内存地址
  3. 一个内存单元为一个字节
  4. 指针在32位平台是4个字节,在64位平台是8个字节

指针的意义

  1. 指针的类型决定了,指针解引用的权限有多大

    1
    2
    3
    //例如
    char*//可以指1个字节
    int*//可以指4个字节

取地址运算

  1. &:取地址后的,需要用%p输出,如果用%x(16进制),则会警告

    • 只有明确的变量才能取他的地址

    • 本地变量存放在堆栈的地方,内存地址由高到底

  2. 指针变量:用于记录地址的变量

  3. int* p,q只将p设成指针,q只是普通变量

  4. 指针用于,函数的传址,当函数需要返回多个值时,需要用指针带回

指针与函数

  1. 传入函数的数组,函数接收到的是函数第一个数的地址,函数中设置接受的数组时,就是设置了指针数组变量是特殊的指针

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    void minmax(int arr[])//这里
    {
    arr[0]=11;
    }
    //上面的函数还可以设置成
    void minmax2(int* a)
    {
    a[0]=11;//与上面结果一致
    }
    int main()
    {
    int arr[]={};
    minmax(arr);
    printf("%d",arr[0])
    return 0;
    }
    //结果是11,因为设置函数时,用了int arr实际上是设置了指针
    • 因此在使用数组作为函数变量时,有两种方法:
      • int arr
      • int* a
    • arr的地址也就是arr[0]的地址
  2. 数组变量是const(限定的变量不允许被改变)的指针,所以不能被赋值,数组之间也不能互相赋值

    1
    2
    3
    4
    5
    6
    7
    8
    //例子:
    int main()
    {
    int a[]={1,2};
    int b[]={};
    a=b;//不能这样写
    return 0;
    }

指针与const

  1. 指针可以是const,修饰的值也可能是const

    1
    2
    3
    4
    int i=0;
    const int *p=&i;
    *p=25;//因为使用const修饰p所以不能再使用,*对i进行修改
    //但是可以通过,直接对i进行修改
  2. 判断被const的标志

    1
    2
    3
    const int* p1=&i;
    int const *p2=&i;
    //第一个和第二个是一样的,const在*的前面,表示所指的东西不能被修改,const在*的后面表示指针不能被修改
  3. const修饰数组表示,数组里面的每一个元素都被const

指针的运算

  1. 指针+1,增加一个指针所指的类型,同理对n也有意义,对-也有意义,减出的结果是,差n个指针所指的类型(元素个数)
1
2
3
4
5
6
7
8
int a=0;
int* p=&a;
pfintf("p=%d",p);
pfintf("p+1=%d",p+1);//p+1为p+4,因为p增加了一个int 的大小
char b=0;
char*q=&b;
printf("q=%d",q);
printf("q+1=%d",q+1);//q+1为q+1,因为q增加了一个char的大小
1
2
3
4
char ac[]={0,1,2,3,45,6,7,8};
char *p=ac;
//*p->ac[0]
//*(p+1)->ac[1]
  1. 如果地址加1就没有实际意义
  2. 0地址, 是不能随便触碰的地址如果使用NULL效果和0地址一样,有些编译器,若果强制使用0地址,则可以用NULL
  3. 指针和指针相减的前提是两个指针指向同一个指针
  4. 指针加指针没有什么意义

指针的类型转换

  1. 强制类型转换,可以用于指针的赋值

指针的用处需要传入较大的数据用作参数

  1. 传入数组对数组操作

  2. 函数返回不止一个结果

  3. 用函数修改不止一个变量

  4. 动态申请内存

动态内存分布

  1. malloc:库函数为<stdlib.h>

    • malloc申请的空间的大小是以字节为单位的,返回的结果是void*,需要类型转换为自己需要的类型

    • 同时需要使用,free()将地址归还,括号里面填存储地址的变量,可以使用free(NULL)

    • 如果申请失败的话就会返回0或者NULL

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      #include<stdio.h>
      #include<stdlib.h>


      int main()
      {
      int number;
      int* a;
      int i;
      printf("输入空间大小");
      scanf("%d",&number);
      a=(int*)malloc(number*sizeof(int));
      //第一个int*是将malloc返回值强制转换为int*,因为a是int*
      //(number*sizeof(int)),*指的是乘法,number,是我们想要的大小,但是需要×相应的类型才能得到,
      free(a);//使用malloc需要归还
      }
  2. 使用malloc常见问题

    • 使用了malloc没有free
    • 错过了free的时机
    • freefree

野指针

  1. 指针指向的位置是不可知的为野指针

  2. 造成原因

    • 指针没有初始化

      • 指针的初始化为NULL
      1
      2
      3
      4
      5
      int *i;
      *i=20;
      //这里i 就是野指针
      //因为i没有初始化,局部变量i默认为随机值,随机的位置来访问i,也就是非法访问

    • 指针越界也会造成野指针

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      int main()
      {
      int arr[10]={0};
      int* p =arr;
      int i;
      for(i=0;i<=10;i++)
      {
      *p=i;
      p++;//这里需要循环10次,但是第10次的时候已经越界,这时候是野指针
      }
      return 0;
      }
    • 指针指向的空间释放

  3. 如何有效规避野指针

    • 指针初始化NULL
    • 小心指针的越界
    • 指针指向空间及时释放指针为NULL
    • 检查指针的有效性
  4. 空指针没有权限使用

    • 使用指针时,最好判断是否为NULL

      1
      2
      3
      4
      5
      6
      int *p=NULL;

      if(p!=NULL
      {
      *p=20;
      }//最好判断一下,可以减少代码出错

指针的标准:

允许指向数组元素的指针指向数组后面一个地址,不允许指向前面一个地址

  1. 例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #include<stdio.h>

    #define count 5

    int main()
    {
    int arr[count]={0};
    int *p=NULL;
    int i=count;
    for(p=&arr[count];p>&arr[0];)
    {
    --i;
    *--p=i;
    //先--,再解引用
    printf("%d,%d\n",arr[i],*p);

    }

    return 0;
    }

指针和数组

  1. 数组名:是数组首元素的地址

    1
    2
    3
    4
    int arr[10];
    int *p=arr;
    //*(p+2)<==>arr[3]<==>*(2+p)<==>*(2+arr)<==>*(arr+2)<==>2[arr]<==>p[2]
    //因为编译器在编译的时候,将arr[2]-->*(arr+2),所以我们可以运用交换率,arr[2]=2[arr]

二级指针

  1. 指向指针的指针,被称作为二级指针

    1
    2
    3
    4
    5
    6
    7
    8
    int a=8;
    //int为a的类型
    int *pa=&a;
    //*为指针变量,int 为a的类型
    int* *ppa=&pa;//ppa是二级指针变量
    //第二个*为指针变量,第一个int*为pa的类型
    inte***pppa=&ppa;
    //三级指针
  2. 使用:

    1
    2
    3
    *pa=a;
    *ppa=pa;
    **ppa=a;

指针数组

  1. 存放指针的数组

    1
    int* parr[10];//指针数组,cun'f

初始指针
https://tsy244.github.io/2023/04/20/C/初始指针/
Author
August Rosenberg
Posted on
April 20, 2023
Licensed under