• 指针杂谈


    指针杂谈

    指针注意事项

    • 指针必须声明,并且初始化

    • 函数参数列表中的数组实际上是指针!!!所以一般需要传递数组长度,而不能使用sizeof(array) / sizeof(int)

    • *sizeof(array) == sizeof(int )

    • 但是可以使用数组的运算符[ ]来进行运算

    • 数组变量本身表达地址,所以

      •   int a[10];
          int *p = a;//无需使用&取地址
        
      • 但是数组的单元表达的是变量,需要用&取地址

      •   a == &a[0]
        
    • []运算符也可以对数组做,也可以对指针做:

      •   p[0] <==> a[0]
        
    • *运算符可以对指针做,也可以对数组做:

      •   *a = 25;
        
    • 数组变量是const的指针,所以不能被赋值

      •   int a[] <==> int * const a=...
        

    指针与const(适用于C99)

    指针本身可以是const,其指向的值也可以是const

    指针是const

    表示一旦得到了某个变量的地址,不能再指向其他变量

    int *const q = &i;//q是const
    *q = 26;//OK
    q++; //ERROR
    

    指针指向的值是const

    表示不能通过这个指针去修改那个变量(并不能使那个变量成为const),p可以指向其他变量,i也可以重新赋值为其他。不变的是:不能通过*p去做赋值!!!

    const int *p = &i;
    *p = 26; //ERROR! (*p)是const
    i = 26; //OK
    p = &j;//OK
    

    练习

    int i;
    const int* p1 = &i;	//是指不能通过p1去修改值---->通过指针不可修改
    int const* p2 = &i;	//同上
    int *const p3 = &i;	//p3不能再去指向其他变量---->指针不可修改
    
    /*方法:判断哪个被const了的标志是const在*的前面还是后面?
    
    const在前面,说明它所指向的东西不能被修改
    const在后面,说明指针不能被修改
    
    */
    

    技巧

    保护数组值

    因为把数组传入函数时传递的是地址,所以那个函数内部可以修改数组的值,为了保护数组内部不被函数破坏,可以设置为const

    int sum(const a[], int length);
    

    指针运算

    指针相加

    char a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    char *p  = a;
    printf("p = %p
    ", p);
    printf("p+1 = %p
    ", p+1);
    
    int b[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int *q  = b;
    printf("q = %p
    ", q);
    printf("q+1 = %p
    ", q+1);
    

    sgvOIK.png

    指针+1的意思不是简单的地址值+1,而是指针指向下一个单元!!!

    这也解释了为什么数组运算可以和指针一样,*p 就相当于a[0],*(p+1)就相当于a[1]

    指针相减

    指针相减计算结果不是他们之间的距离之差,而是他们地址之差/sizeof(类型)

    特殊形式

    *p++

    • 取出p所指的数据,然后将p指针移到下一单元去
    • *的优先级虽然高,但是没有++高
    • 常用于数组类的连续空间操作
    • 在某些CPU上,这可以直接被翻译为一条汇编指令

    指针比较

    • < <= == >= > !=都可以对指针做
    • 比较它们在内存中的地址
    • 数组中的单元的地址肯定都是线性递增的

    0地址

    • 内存中肯定存在0地址,但是通常0地址是一个不能随便碰的地址
    • 所以地址在实际中不应该具有0值
    • 因此可以使用0地址来表示特殊的事情:
      • 返回的指针是无效的
      • 指针没有被真正初始化(先初始化为0)
    • NULL是一个预定定义的符号,表示0地址
      • 有的编译器不愿意你用0来表示0地址

    指针类型

    • 无论指向什么类型,所有的指针的大小都是一样的,都是地址
    • 但是指向不同类型的指针是不能直接互相赋值的,因为类型不同
    • 以上是为了避免用错指针

    指针的类型转换

    • void*表示不知道指向什么类型的指针

      • 计算的时候与char*相同(但不相通)
    • 指针也可以转换类型

      •   int *p = &i; 
          void *q = (void*)p;
        
      • 这转换并没有改变p所指的变量的类型,i仍然是整型,而是让人们用不同的眼光通过p看它所指向的变量(我不再认为你是int类型,而是void)

    指针用处

    • 需要传入较大的数据时用作参数
    • 传入数组后对数组做操作
    • 函数返回不止一个结果
      • 需要用函数来修改不止一个变量
    • 动态内存的申请...

    动态内存分配

    在C99出来之后,可以使用变量来定义数组的大小,例如:

    int num;
    scanf("%d", &num);
    int arr[num];
    

    在C99之前,是需要动态申请内存的,例如:

    int *a = (int*)malloc(n*sizeof(int));	//因为malloc返回的是void*,所以对于a来说还需要强转一下
    
    ...
    free();
    
    //动态申请之后,在程序结束时候,要free()一下,释放内存!
    

    注意:

    • 需要导入头文件<stdlib.h>

    • 向malloc申请的空间的大小是以字节为单位的

    • 返回的结果是void*,需要类型转换为自己需要的类型

    •   (int*)malloc(n*sizeof(int))
      
    • free()

      • 把申请得来的空间还给系统
      • 申请过的空间都需要还
      • 只能还申请来的空间的首地址,如果地址变过了,则会出错!

    因为系统内存空间是有限的,如果系统在某个时间内存满了,此时malloc函数向系统申请内存空间,会怎么样呢?

    • 如果申请失败则返回0,或者NULL
    • 怎么知道系统能分配给你多大空间呢?
  • 相关阅读:
    修改spring boot 启动logo
    查看jvm常用命令
    intellij IDEA破解
    hdu 新生晚会
    How many prime numbers(素数)
    2077 汉诺塔IV
    Factorial
    双人黑白块
    EasyX
    七夕情人节
  • 原文地址:https://www.cnblogs.com/Arong123/p/14320445.html
Copyright © 2020-2023  润新知