当我创建指向某个结构的指针时,我是否必须将其设置为NULL,然后分配它然后使用它?为什么?
Lev*_*von 12
不,你不必将其设置为NULL,但有些人认为这是一个好习惯,因为它为新指针赋予一个值,使其明确表示它不指向任何东西(尚未).
如果您正在创建一个指针,然后立即为其指定另一个值,那么将其设置为没有多大价值NULL.
不过,最好NULL在释放指向的内存后设置指针.
不,在声明它时,没有要求(就语言而言)将指针变量初始化为任何东西.从而
T* ptr;
Run Code Online (Sandbox Code Playgroud)
是一个有效的声明,它引入了一个以ptr不确定值命名的变量.您甚至可以以某种方式使用变量,而无需先分配任何内容或将其设置为任何特定值:
func(&ptr);
Run Code Online (Sandbox Code Playgroud)
根据 C 标准,不初始化自动存储变量会使其值不确定。
当您的指针具有不确定值时,绝对鼓励您将指针设置为 NULL。使用具有不确定值的指针是未定义行为,如果您习惯于 C 编程并且来自更高级别的语言,则您可能无法正确掌握这一概念。
未定义的行为意味着任何事情都可能发生,这是 C 标准的一部分,因为 C 的哲学是让程序员有责任控制事物,而不是保护他免受错误的影响。
你想避免代码中的未定义行为:当任何行为可能发生时,调试东西是非常困难的。它不会被编译器捕获,并且您的测试可能总是通过,而不会注意到该错误,直到纠正它的成本非常高。
如果你做这样的事情:
char *p;
if(!p) puts("Pointer is NULL");
Run Code Online (Sandbox Code Playgroud)
您实际上并不知道该if控制是对还是错。这在大型程序中极其危险,您可以在其中声明变量,然后在空间和时间很远的地方使用它。
引用释放内存时的概念相同。
free(p);
printf("%s\n", p);
p = q;
Run Code Online (Sandbox Code Playgroud)
你实际上并不知道最后两个语句你会得到什么。你不能正确地测试它,你不能确定你的结果。您的代码似乎可以工作,因为释放的内存会被回收,即使它可能已被更改...您甚至可以覆盖内存,或损坏共享相同内存的其他变量。所以你仍然有一个迟早会表现出来的错误,并且很难调试它。
如果您将指针设置为 NULL,您可以保护自己免受这些危险情况的影响:在您的测试期间,您的程序将具有确定性、可预测的行为,该行为将快速且廉价地失败。你得到一个段错误,你发现了错误,你修复了错误。干净简单:
#include <stdio.h>
#include <stdlib.h>
int main(){
char* q;
if(!q) puts("This may or may not happen, who knows");
q = malloc(10);
free(q);
printf("%s\n", q); // this is probably don't going to crash, but you still have a bug
char* p = NULL;
if(!p) puts("This is always going to happen");
p = malloc(10);
free(p);
p = NULL;
printf("%s\n", p); // this is always going to crash
return 0;
}
Run Code Online (Sandbox Code Playgroud)
因此,当您初始化一个指针时,尤其是在大型程序中,您希望它们被显式初始化或设置为 NULL。您永远不希望它们获得不确定的值。我应该说,除非你知道自己在做什么,但我宁愿永远不要。