初始化时是否需要调用pointer = NULL?

时间:2012-09-03 19:37:51

标签: c pointers alloc

当我创建指向某个struct的指针时,是否必须将其设置为NULL,然后分配它然后使用它?为什么?

6 个答案:

答案 0 :(得分:10)

不,您不必将其设置为NULL,但有些人认为这是一种很好的做法,因为它为新指针提供了一个值,使其显式它没有指向任何东西(尚)。

如果你正在创建一个指针,然后立即为它分配另一个值,那么将它设置为NULL真的没什么价值。

最好在释放指向的内存后设置指向NULL的指针。

答案 1 :(得分:7)

不,在声明它时,没有要求(就语言而言)将指针变量初始化为任何东西。因此

T* ptr;

是一个有效的声明,它引入了一个名为ptr的变量,该变量具有不确定的值。您甚至可以以某种方式使用变量,而无需先分配任何内容或将其设置为任何特定值:

func(&ptr);

答案 2 :(得分:3)

根据C标准,未初始化自动存储变量将使其值不确定。

无论哪种情况,只要您的指针具有不确定的值,就绝对建议您将指针设置为NULL。具有不确定值的指针的使用是不确定的行为,如果您习惯于C编程并且来自高级语言,则可能无法正确理解该概念。

未定义的行为意味着任何事情都会发生,这是C标准的一部分,因为C的哲学是让程序员负担控制事情的重担,而不是保护他免受错误的侵害

您要避免代码中未定义的行为:任何行为都可能发生时,调试东西非常困难。它不会被编译器捕获,并且您的测试可能始终会通过,直到发现该错误的代价很高时,该错误才会被忽略。

如果您执行以下操作:

char *p;
if(!p) puts("Pointer is NULL");

您实际上并不知道if控件是true还是false。这在大型程序中非常危险,在大型程序中,您可能会声明变量,然后在时空很远的地方使用它。

引用释放的内存时的概念相同。

free(p);
printf("%s\n", p);
p = q;

您实际上并不知道最后两个语句会得到什么。您无法正确测试它,无法确定结果。您的代码似乎可以正常工作,因为即使已更改释放的内存,回收的内存也可能被更改了……您甚至可以覆盖内存,或者破坏共享同一内存的其他变量。因此,您仍然有一个迟早会出现的错误,并且可能很难调试。

如果将指针设置为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;
}

因此,在初始化指针时(尤其是在大型程序中),您希望将其显式初始化或设置为NULL。您不希望他们获得不确定的价值,永远不要。我应该说,除非您知道自己在做什么,但我更喜欢从不

答案 3 :(得分:2)

不,不要忘记初始化必须是空指针。现代C中一个非常方便的习惯是在第一次使用时声明变量

T * ptr = malloc(sizeof *ptr);

这可以避免您在记住类型以及变量是否已经初始化时遇到很多麻烦。只有当你不知道它在哪里(或者甚至是)稍后被初始化时,你最终应该将它初始化为空指针。

因此,根据经验,始终将变量初始化为适当的值。如果您手边没有更好的类型,那么“适合0类型”总是一个不错的选择。对于所有类型,C都是这样制作的,这样就可以了。

在大多数情况下,不初始化变量是过早优化。当您发现存在真正的性能瓶颈时,只需查看变量。特别是如果在使用初始值之前在同一函数内存在赋值,并且现代编译器将优化初始化输出。首先考虑你的程序的正确性。

答案 4 :(得分:0)

除非你不想让它悬挂一段时间,否则你不必这样做。你知道你在解放后应该(防御风格)。

答案 5 :(得分:0)

您不必初始化为NULL。如果您打算立即分配,可以跳过它。

At可用于错误处理,如下例所示。在这种情况下,在p分配后中断结束会使q保持未初始化状态。

int func(void)
{
    char *p;
    char *q;

    p = malloc(100);
    if (!p)
        goto end;

    q = malloc(100);
    if (!q)
        goto end;

    /* Do something */

end:
    free(p);
    free(q);

    return 0;
}

此外,这是我的个人品味,总是使用calloc分配结构。字符串可以使用malloc

分配未初始化