• C语言指针总结


    概念

      指针是什么?指针就是地址,众所周知,内存中的每个存储单元都有自己的地址,根据存储地址可以准确的找到该内存单元,所有通常把这个内存地址称为指针。所有指针就是实际地址。在c语言中,使用一个变量来存储指针,那么这个就是指针变量。

      一个指针的值就是某个内存单元的地址(或者指针)。指针是指地址是一个常量;指针变量时指取值为地址的变量

     

    指针的定义方式和初始化

      

     1 //单个的定义指针
     2 
     3 int *p;
     4 
     5 //一条语句定义多个指针
     6 
     7 int *p1,*p2;
     8 
     9 
    10 //使用typedef来便捷定义
    11 
    12 typedef int *ZHE;
    13 ZHE a,b,c;
    14 
    15 ////////////////////////////
    16 //指针的初始化
    17 //方式一
    18 int a;
    19 int *p=&a;
    20 
    21 //方式二
    22 int a;
    23 int *p;
    24 p=&a;
    25 
    26 //方式三
    27 
    28 int *p,*q;
    29 int a=90;
    30 p=&a;
    31 q=p;

    赋值指针注意

    1. 不同类型的指针赋值需要强制转换
    2. 不允许将一个值直接给指针变量(0除外)
    3. 在c语言中,auto变量不能赋值给static指针变量。
      int a=90;
      static int *p=&a;
      
      //////////////////////////////
                       错误
      /////////////////////////////

    实例

    void main() {
        int a,*p;
        p = &a;
        *p = 11;
        a++;
        printf("a=%d,*p=%d", a, *p);
    }

    指针运算

      指针是地址,地址是一种无符号整数;指针只有加法和减法,没有乘除法,因为两个地址之间的没有任何意义。但是两个地址之间的加法也没有任何意义,而两个地址相减表示两个指针之间的内存单元数。

      指针的加减的结果=当前地址+/-n*sizeof(type);例如:int *pi;pi的值是2000的话,那么pi++,就是2000+1*sizeof(int)=2002;其他类型也是类似。

      如果两个指针p1,p2存在如下关系:

      p1==p2:p1,p2指向同一个内存单元;

        p1>p2;表示p1处于高地址位置;

        p1<p2:表示p1处于低地址位置。

    指针数组之间的关系

      数组的指针其实就是数组再内存中的起始地址。

    void main() {
        int a[10];
        int k;
    
        for (k = 0; k < 10; k++)
            a[k] = k;//  *(a+k)=k;
    }

      数组元素的几种赋值方法

        

    void main() {
        char str[10];
        int i;
        //常规方法 
        for (i = 0; i < 10; i++)
            str[i] = 'a' + i;
        //指针方法
        char *array = str;
        for (i = 0; i < 10; i++)
            *(array + i) = 'a' + i;
        //指针自增方法
        for (i = 0; i < 10; i++)
            *array++ = 'a' + i;
    }

      在上面3种方法中,第三种方法 array指向的是str[9]的下一个单元,显然超出了数组所占的内存区域,这是越界现象,因为C语言不会对数组越界检查,所以需要程序员自己控制。

    在后面加一个array=str即可。

    多维数组指针的定义方式

    void main() {
        int a[2][3] = { { 1,2,3 },{ 4,5,6 } };
        int(*p)[3];
        int i,j;
    
        p = a;
        for (i = 0; i < 2; i++)
            for (j = 0; j < 3; j++)
                printf("%d", *(p + 3 * i + j));//  printf("%d",*(p[i]+j))
    
    }

    数组指针与指针数组的区别

    1. 定义的方式不一样,数组指针  int (*p)[5];  指针数组 int *p[5];
    2. 表示的东西不一样,数组指针 p是指针变量,不是数组名,可以对此赋值;指针数组p是数组名,不可赋值。
    3. 存储的对象不一样;数组指针存储的是普通值,指针数组存储的是指针。
    void main() {
        int i, j, k;
        int a, b, c, d, e, f;
    
        int *p[6] = { &a,&b,&c,&d,&e,&f };
    
        for (i = 0; i < 6; i++) {
            scanf("%d", p[i]);
        }
    
        for (i = 0; i < 5; i++) {
            for (j = i+1; j < 6; j++) {
                if (*p[i] > *p[j]) {
                    k = *p[i];
                    *p[i] = *p[j];
                    *p[j] = k;
                }
            }
        }
    
        for (i = 0; i < 6; i++)
            printf("%d ", *p[i]);
    }

    字符指针

    void main() {
        char str[] = { "i am your father" };
        char ch;
        char *p, *q;
        p = str;
        q = p + strlen(str) - 1;
    
        while (p < q) {
            ch = *q;
            *q-- = *p;
            *p++ = ch;
        }
        printf("%s", str);
    }

    指针与动态内存分配

    我们以往的定义如  int a[10]; int b;等等都是静态内存分配,这些内存在程序运行前就分配好了,不可改变。

    假如我们需要记录一个班级的学生成绩,那么我们要定义一个数组,但是我们常规定义数组要确定数组的大小。如果我们开辟一个1000的大小的数组,如果人数多,不够用,人数少造成浪费。然而动态内存分配就解决了这个问题。

    动态内存分配的方式

    1. malloc:void * malloc(unsiged int size);
      int n ,*p;
      
      scanf("%d",&n);
      
      p=(int *)malloc(n*sizeof(int));
    2. calloc:void *calloc (unsigned int n,unsigned size);功能和malloc一样,但是他将赋初始值。
    3. realloc:void *realloc(void *p,unsigned int size):在原来的空间不够用的时候重新开辟更大的空间,优点是,原来的数据时保存的。

    内存的释放

    使用free(void * p)释放无用的内存,避免浪费内存。

    二级指针

    int a=20;
    int *p;
    int **k;
    
    p=&a;
    **k=&p;

    函数指针

      使用背景,假如有多个函数,他们的参数和返回值都完全相同,那么我们使用一个函数指针对这些函数统一调用。

    #include<stdio.h>
    #include<conio.h>
    #include<string.h>
    
    int max(int a, int b);
    int min(int a, int b);
    int sum(int a, int b);
    
    int func(int a, int b, int(*fun)(int, int));
    
    void main() {
        int a = 2;
        int b = 3;
        int res;
        res=func(a, b, max);
        res=func(a, b, min);
        res=func(a, b, sum);
    }
    
    int func(int a, int b, int(*fun)(int, int)) {
        return (*fun)(a, b);
    }
    
    int max(int a, int b) {
        return a > b ? a : b;
    }
    
    int min(int a, int b) {
        return a < b ? a : b;
    }
    
    int sum(int a, int b) {
        return a + b;
    }

    ps:一个函数的返回值是指针时应该注意:在返回之前一定要保证返回的指针时有效的,不是野的,因为auto在使用完后会被立即销毁,所有函数内部需要用static修饰

    int *get(int num) {
        static int a[100];
        ////
        ////
        ////
        ////
        return (a);
    }
  • 相关阅读:
    HDU 1009 FatMouse' Trade
    python正则表达式
    Python学习week5
    Python学习week4
    Python学习week3
    Python学习week2
    Python学习week1
    生活的艰辛(最小割,最大密度子图)
    最大获利(最小割,最大权闭合图,最大密度子图)
    最大密度子图
  • 原文地址:https://www.cnblogs.com/yangdagaoge/p/9780850.html
Copyright © 2020-2023  润新知