ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

搞懂C语言的指针(四) 空指针|蒙圈的不止你一个

搞懂C语言的指针(四) 空指针|蒙圈的不止你一个 在上一篇我分享了的内容及理解在这里我们会搞懂空指针到底是怎么回事。在学C语言时看到自己写得程序终于通过了编译感到无比兴奋。但是一运行就被一个接一个的segmentation fault搞蒙了。估计这是所有接触过C语言的人的共同遭遇。究其原因无非是你还没有搞懂指针和空指针。那么空指针是什么呢一句话空指针Null Pointer就是不指向任何有效内存地址的指针。因此我觉得当初把Null Pointer翻译成无效指针会更好一点起码不会引起初学者的误解。把一个城市当作内存的话空指针不是指那些没有人住房子而是专门用来指那些在城市里不存在的房子当然那些烂尾楼也可以当作空指针。但是它又是一个常量作为NULL被定义在各种头文件里。比如stddef.h stdio.h stdlib.h string.h time.h wchar.h#define NULL ((void*)0) //这个常量的定义会随着编译器的不同而不同 //现在为了保持C和C的兼容也有的定义为下面的形式 // C compatible: #define NULL 0 // C incompatible: #define NULL (10*2 - 20) #define NULL ((void*)0) // since C23 (compatible with C11 and later) #define NULL nullptr换个说法任何有效的指针都不能成为空指针。其实它和C语言中其他类型的常量没有本质的区别比如整数有常量:016进制有常量:0x00char型有常量:\0。因为指针也有类型所以当把空指针变换成void*char*int* 时就会生成相对类型的空指针。例8:#include int main(void) { void *p 0x0; // 右边为空指针的常量p为空指针 int *q 0x0; // 0x0为整数的常量是否为空指针在(1)(8)(9)可以确认 int n 0; /* A */ printf((A) p [%p]\n, p); // %p的输出会会依存于系统 if(p NULL) // (1) NULL 空指针常量 // printf(OK, integer constant expression 0x0 is a null pointer constant in your computer.\n); else printf(* WARNING\n * Integer constant expression 0x0 may not be with \the value 0\ in your computer.\n * Or, NULL may be incompatible with ISO:C11.\n); /* B */ p (void *)0; // (2) 右边为看指针常量p空指针 // (void *)0 是否为空指针常量通过(3)确认 printf((B) p [%p]\n, p); if(p NULL) // (3) printf(OK, (void *)0 is a null pointer constant in your computer.\n); else printf(* WARNING\n * Integer constant expression 0 may not be with \the value 0\ in your computer.\n * Or, NULL may be incompatible with ISO:C11.\n); /* C */ printf((C) p [%p]\n q [%p]\n, p, q); if(q (int *)p) // (4) printf(OK, any two null pointers shall compare equal [C11 \u00A76.3.2.3, 4; \u00A76.5.9, 6].\n); else printf(* WARNING\n * Either integer constant expression 0x0 or 0 may not be with \the value 0\ in your computer.\n); /* D */ q n; // (5) 右边既不是空指针常量也不是空指针 // 所以q不是空指针 printf((D) q [%p]\n, q); if(q ! NULL) // (6) printf(OK, q is not a null pointer.\n); else printf(* WARNING\n * NULL may be broken.\n); /* E */ p 0x0; // (7) printf((E) p [%p]\n q [%p]\n, p, q); if(q ! p) // (8) printf(OK, q is not a null pointer.\n); else printf(* WARNING\n * Integer constant expression 0x0 may not be with \the value 0\ in your computer.\n); /* F */ printf((F) q [%p]\n, q); if(q ! 0x0) // (9) printf(OK, q is not a null pointer.\n); else printf(* WARNING\n * Integer constant expression 0x0 may not be with \the value 0\ in your computer.\n); return 0; } //执行结果如下 /* (A) p [0x0] OK, integer constant expression 0x0 is a null pointer constant in your computer. (B) p [0x0] OK, (void *)0 is a null pointer constant in your computer. (C) p [0x0] q [0x0] OK, any two null pointers shall compare equal [C11 xc2xa76.3.2.3, 4; xc2xa76.5.9, 6]. (D) q [0x16fdfeb54] OK, q is not a null pointer. (E) p [0x0] q [0x16fdfeb54] OK, q is not a null pointer. (F) q [0x16fdfeb54] OK, q is not a null pointer. */既然空指针是无效指针那么专门定义一个空指针又有什么用呢以简洁为宗旨的C语言当然不会做无用之功。在C语言中空指针的作用基本如下1、初始化尚未被赋予任何有效内存地址的指针变量。例9:#include int main() { //声明一个空指针 int* ptr NULL; // if (ptr NULL) { printf(Pointer does not point to anything); } else { printf(Value pointed by pointer: %d, *ptr); } return 0; }2、用于在访问任何指针变量之前检查其是否为空指针。这样我们可以在与指针相关的代码中进行错误处理例如仅当指针变量不为空时才对其进行解引用。例10:#include #include int main() { //分配一段动态内存 int* ptr (int*)malloc(5 * sizeof(int)); //判断是否分配成功 if (!ptr) { printf(Memory Allocation Failed); exit(0); } free(ptr); return 0; }3、用于在不希望传递任何有效内存地址时将空指针传递给函数参数。例11:#include void foo(int* string) { if (string NULL) { printf(NULL Pointer Passed); return; } printf(Non-Null Pointer Passed); } // int main() { foo(NULL); return 0; }4、空指针用于树、链表等数据结构中表示结束位置。例12:#include #include /* 定义链表节点 */ struct Node { int value; struct Node *next; // 指向下一个节点 }; int main(void) { /* 手动创建三个节点 */ struct Node *n1 malloc(sizeof(struct Node)); struct Node *n2 malloc(sizeof(struct Node)); struct Node *n3 malloc(sizeof(struct Node)); n1-value 1; n2-value 2; n3-value 3; /* 串成一个链表 */ n1-next n2; n2-next n3; n3-next NULL; // 关键NULL 表示“链表到此结束” /* 遍历链表 */ struct Node *p n1; while (p ! NULL) { // 通过判断空指针知道是否结束 printf(%d\n, p-value); p p-next; } /* 释放内存 */ free(n1); free(n2); free(n3); return 0; } //执行结果 /* 1 2 3 *最后说一下空指针和Void指针的区别空指针NULL Pointer通用【万能】指针Void Pointer空指针不指向任何东西它是一个特殊的指针变量一个指向任何类型的指针任何类型的指针变量都可以被设置为空指针只有它才可以被定义为void型所有的空指针都相等Void指针可以是不同空指针在头文件里被定义为一个常量值void指针是一种指针的类型也就是说它是一种数据类型例如: int *ptr NULL;例如: void *ptr;以上关于空指针的概念和应用您理解了吗
返回列表