【劲爆】C语言指针心碎日记 by 一颗被指针扎过的心 | 独家爆料 | 那些你可能未曾听闻的指针故事 | 持续更新

141 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。 如果你喜欢这个系列,欢迎点赞收藏关注评论。文章若有错误或是不合适的地方欢迎指正,我们一起进步 : -)


你到底是谁?指针数组 与 数组指针 的区别

指针数组:

本质是一个数组,一个指针的数组

声明

char *arr[4]
/* 等价于 */
char *(arr[4])

解释

  • arr是一个数组
  • arr数组包含4个元素
  • 每个数组元素是一个char *类型的指针
  • 每个指针存放着对应字符的首地址

数组指针:

本质是一个指针,一个数组的指针

声明

char (*pa)[4]	/* pa即 Pointer of Array */

解释

  • pa是一个指针
  • pa指向一个char [4]的数组
  • 每个数组元素是一个char类型的变量

空指针的迷思——我指向空,但我不为空

空指针 (Null Pointer)是一个已宣告、但并未指向一个有效对象的指针 那么,让我们试着思考一个脑筋急转弯:当指针所指地址上为空值时,指针为NULL吗?

正确答案: 不 更具体的说: 一个非NULL的指针所指向的地址,该地址上可以是空值(NULL) 但是一个指针一旦被成功分配了(指向)某块内存空间,那么不论这块内存空间上有没有数据,该指针都不为NULL 举个栗子🌰:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/**
 * NULL 是被定义在 _types.h 中的: #define __DARWIN_NULL ((void *)0)
 * 一个指针,只要被分配了内存空间,那么它就不为NULL;
 * 只有内存分配失败(内存已满,没有空间再分配)的时候,该指针才会为 NULL
 */
int main()
{
    char *str;
    // 给 str 分配内存空间
    // 合理的内存分配
    str = (char *)malloc(20);
    // str = (char *)malloc(2147483647); // 2^31 - 1 = 2147483647, the max value of a 32-bit signed integer
    // 超大的内存请求
    // str = (char *)malloc(421341234232345); // failed
    // str = (char *)malloc(9223372036854775807); // 2^63 - 1= 9223372036854775808, the max value of a 64-bit signed integer
    // strcpy(str, "hello world");
    // 如果指针为空
    if (str == NULL)
    {
        printf("分配内存失败!str 指针仍为 NULL\n");
        return 0;
    }
    else
    {
        // 如果指针不为空,打印指针所指位置的内容
        printf("String content = \"%s\",  Address = %u.\n", str, str); // 此时虽然指向的内容是空字符串,但指针不为 NULL
        // free the pointer
        free(str);
    }

    return (0);
}

在上面这段代码中: 如果14/15行被执行,则会运行到第29行,打印字符串内容和地址,此时虽然指向的内容是空字符串,但指针不为 NULL 如果17/18行被执行,则会运行到第23行,提示你str指针并没有被成功分配空间,它仍然是一 个NULL Pointer

目前我接触到操作系统的源码中,经常使用【为指针申请内存-判断指针是否为NULL】这套连招,来判断是该进程否成功申请到内存。如果没有,则返回相应的 error code


野指针——心里有了不该有的人,是谁我不说

野指针是一个指向不可用内存区域的指针。通常对这种指针进行操作的话,将会使程序发生不可预知的错误。就好像你爱上了一个不该爱的人,如果表白了,你的生活会变的一团糟。

野指针不是NULL指针,而是指向“垃圾”内存的指针。人们一般不会错用NULL指针,因为用if语句很容易判断。但是“野指针”是很危险的,if语句对它不起作用。野指针的成因主要有两种:

  1. 指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。
  2. 指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针。别看free和delete的名字恶狠狠的(尤其是delete),它们只是把指针所指的内存给释放掉,但并没有把指针本身干掉。通常会用语句if (p != NULL)进行防错处理。很遗憾,此时if语句起不到防错作用,因为即便p不是NULL指针,它也不指向合法的内存块。例如:
    char *p = (char *) malloc(100);
    
    strcpy(p, “hello”);
    
    free(p); // p 所指的内存被释放,但是p所指的地址仍然不变
    
    if(p != NULL) // 没有起到防错作用
    
    strcpy(p, “world”); // 出错