is it necessary to call pointer = NULL when initializing?
Asked Answered
S

6

23

when I create a pointer to certain struct, do I have to set it to NULL, then alloc it then use it? and why?

Siu answered 3/9, 2012 at 19:37 Comment(2)
Q: Do you have to initialize to NULL before using, and reset to NULL afer freeing it? A: No, you don't have to. But it's an extremely good habi t:)Trichromat
It is necessary only when you expect it to have a default value. As pointers, just like other variables will hold garbage value unless it is initialized.Floor
P
11

No, there is no requirement (as far as the language is concerned) to initialize a pointer variable to anything when declaring it. Thus

T* ptr;

is a valid declaration that introduces a variable named ptr with an indeterminate value. You can even use the variable in certain ways without first allocating anything or setting it to any specific value:

func(&ptr);
Pinon answered 3/9, 2012 at 19:47 Comment(5)
But let's face it: T* ptr = NULL; is "better".Trichromat
To nitpick, T* ptr; is not a statement in C, it's a declaration. I have heard it's a statement in C++ though.Reikoreilly
I am confused in understanding when a pointer should be initialized and when should we allocate memory for that pointer (for example a structure pointer)Misfeasance
Calling func(&ptr) without initializing first and actually doing anything with an unitialized pointer is a recipe for disaster (ie. undefined behaviour). So it is good practice to set the pointer to point to some variable, or at least to nullptr/NULL/0.Pliner
T* ptr; can have any possible value, so it is indeed pointing to somewhere in memory. If you know you're going to overwrite its value (to point to somewhere legit) then it is kind of fine... but let's admit it. C is not helping you with its default behavior so you're going to shoot yourself in the foot if you don't initialize pointers (to NULL or something else)Thigmotropism
P
24

No, you don't have to set it to NULL, but some consider it good practice as it gives a new pointer a value that makes it explicit it's not pointing at anything (yet).

If you are creating a pointer and then immediately assigning another value to it, then there's really not much value in setting it to NULL.

It is a good idea to set a pointer to NULL after you free the memory it was pointing to, though.

Postwar answered 3/9, 2012 at 19:38 Comment(0)
P
11

No, there is no requirement (as far as the language is concerned) to initialize a pointer variable to anything when declaring it. Thus

T* ptr;

is a valid declaration that introduces a variable named ptr with an indeterminate value. You can even use the variable in certain ways without first allocating anything or setting it to any specific value:

func(&ptr);
Pinon answered 3/9, 2012 at 19:47 Comment(5)
But let's face it: T* ptr = NULL; is "better".Trichromat
To nitpick, T* ptr; is not a statement in C, it's a declaration. I have heard it's a statement in C++ though.Reikoreilly
I am confused in understanding when a pointer should be initialized and when should we allocate memory for that pointer (for example a structure pointer)Misfeasance
Calling func(&ptr) without initializing first and actually doing anything with an unitialized pointer is a recipe for disaster (ie. undefined behaviour). So it is good practice to set the pointer to point to some variable, or at least to nullptr/NULL/0.Pliner
T* ptr; can have any possible value, so it is indeed pointing to somewhere in memory. If you know you're going to overwrite its value (to point to somewhere legit) then it is kind of fine... but let's admit it. C is not helping you with its default behavior so you're going to shoot yourself in the foot if you don't initialize pointers (to NULL or something else)Thigmotropism
A
8

According to the C standard, not initializing an automatic storage variable leaves its value indeterminate.

You are definitely encouraged to set pointers to NULL whenever the alternative is your pointer having an indeterminate value. Usage of pointers with an indeterminate value is undefined behavior, a concept that you might not grasp properly if you're used to C programming and come from higher level languages.

Undefined behavior means that anything could happen, and this is a part of the C standard since the philosophy of C is letting the programmer have the burden to control things, instead of protecting him from his mistakes.

You want to avoid undefined behaviors in code: it is very hard to debug stuff when any behavior can occurr. It is not caught by a compiler, and your tests may always pass, leaving the bug unnoticed until it is very expensive to correct it.

If you do something like this:

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

You don't actually know whether that if control will be true or false. This is extremely dangerous in large programs where you may declare your variable and then use it somewhere very far in space and time.

Same concept when you reference freed memory.

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

You don't actually know what you're going to get with the last two statements. You can't test it properly, you cannot be sure of your outcome. Your code may seem to work because freed memory is recycled even if it may have been altered... you could even overwrite memory, or corrupt other variables that share the same memory. So you still have a bug that sooner or later will manifest itself and could be very hard to debug it.

If you set the pointer to NULL, you protect yourself from these dangerous situations: during your tests, your program will have a deterministic, predictable behavior that will fail fast and cheaply. You get a segfault, you catch the bug, you fix the bug. Clean and simple:

#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;
}

So, when you initialize a pointer, especially in large programs, you want them to be explicitely initliazed or set to NULL. You don't want them to get an indeterminate value, never. I should say unless you know what you are doing, but I prefer never instead.

Airlike answered 17/7, 2018 at 10:41 Comment(1)
FYI, dereferencing a null pointer is undefined behavior. While it's most likely to cause a crash, this may not always be the case.Pothunter
S
2

No, don't forget that initialization has to be to a null pointer at all. A very convenient idiom in modern C is to declare variables at their first use

T * ptr = malloc(sizeof *ptr);

This avoids you a lot of hussle of remembering the type and whether or not a variable is already initialized. Only if you don't know where (or even if) it is later initialized, then you definitively should initialize it to a null pointer.

So as a rule of thumb, always initialize variables to the appropriate value. The "proper 0 for the type" is always a good choice if you don't have a better one at hand. For all types, C is made like that, such that it works.

Not initializing a variable is premature optimization in most cases. Only go through your variables when you see that there is a real performance bottleneck, there. In particular if there is an assignment inside the same function before a use of the initial value, andy modern compiler will optimize you the initialization out. Think correctness of your program first.

Shandrashandrydan answered 3/9, 2012 at 22:25 Comment(0)
F
0

You dont have to unless you dont want it to dangle a while. You know you should after freeing(defensive style).

Flinders answered 3/9, 2012 at 19:39 Comment(0)
C
0

You do not have to initialize to NULL. If you intend to allocate it immediately, you can skip it.

At can be useful for error handling like in the following example. In this case breaking to the end after p allocation would leave q uninitialized.

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;
}

Also, and this is my personal taste, allocate structs always with calloc. Strings may be allocated uninitialized with malloc

Crumbly answered 3/9, 2012 at 19:44 Comment(6)
I prefer calloc myself too .. is there ever a reason to use malloc over calloc?Postwar
I, on the other hand, hardly ever find calloc particularly useful.Pinon
There can be a significant performance penalty with calloc, both in terms of the time it takes to zero the memory and the fact that it may cause all the pages in a large allocation to be wired immediately rather than on demand. For small and/or infrequent allocations though the performance penalty is usually insignificant.Molli
@Postwar there's no need to use calloc if you're going to initialize all the members afterwards, to something other than zero.Infallible
@PaulR Ah .. yes, good points (esp with large allocations) .. thanks!Postwar
@Infallible Understood, I just saw all the zeros as a nice default value for newly allocated memory - but no point doing that if it's going to be set to something else.Postwar

© 2022 - 2024 — McMap. All rights reserved.