1

I was implementing Radix Sort which required array of pointer and to avoid segmentation fault I have to initialize it to NULL.

When I tried : struct Node *Bucket[10] = NULL

But it gives :error: invalid initializer

So , my teacher suggested : struct Node *Bucket[10] = {0}

So my question is what is the difference between {0} and NULL and I have also tried :

struct Node *Bucket[10] ;

     for(int i=0 ; i<10 ; i++)
     {
             Bucket[i] = NULL ;
     }

How {0} is same this for loop

Edit 1:

There is an additional question why are we making Bucket[0] .. Bucket[9] as NULL and how does it prevent segmentation fault.

void Radix_Sort(int *Arr)
{
    int max ;

    max = Max_element_in_array(Arr);

    struct Node *Bucket[10] = {0} ;

    for(int exp = 1 ; max / exp > 0 ; exp*=10)
    {
        int k=0 ;

        for(int i=begin ; i<end ; i++)
        {
            Append_a_linked_list(&Bucket[(Arr[i]/exp)%10],Arr[i]);
        }

        for(int j=0 ; j<10 ; j++)
        {
            while( Bucket[j] )
            {
                Arr[k++] = Delete_first_node(&Bucket[j]);
            }
        }
    }
}
  • 2
    memset(Bucket, 0, sizeof(Bucket) / sizeof(Bucket[0])); – SPlatten Apr 20 '20 at 07:32
  • 4
    @SPlatten The third argument to `memset` is the number of bytes, so it should just be `sizeof(Bucket)` – user3386109 Apr 20 '20 at 07:35
  • 1
    @JoopEggen no, since Cxx (I don't remember... C99?) `type array[N] = {0}` is a common way to initialize all elements to 0. – Roberto Caboni Apr 20 '20 at 07:37
  • 20 years java, sorry. – Joop Eggen Apr 20 '20 at 07:39
  • 1
    Technically speaking, C standard doesn't guarantee that `0 == NULL`. Now, I don't remember a single environment in which `0 != NULL`, but in the past did exist. – Roberto Caboni Apr 20 '20 at 07:42
  • @user3386109 No, it should `sizeof(Bucket)/sizeof(Bucket[0])`, – douyu Apr 20 '20 at 07:44
  • @RobertoCaboni @Gerhardh honestly, i'd suggest against initializing an array this way, because a newbie likely will assume that if `{0}` initializes the entire array to zero, `{1}` will initialize the entire array to 1, which it doesn't – Felix G Apr 20 '20 at 07:44
  • @FelixG true. I didn't mean to suggest this way. It was just a response to a (deleted) claim that it would not be valid C code. – Gerhardh Apr 20 '20 at 07:46
  • 3
    @Aoerz That is not correct. If you divide by `sizeof(Bucket[0])` you get the number of elements in the array. Useful for loops but useless for `memset`. `memset` does not care about elements. It takes the size of the whole memory areay. As you don't pass the size of an element, you would only get 10 bytes filled instead of 10 pointers. – Gerhardh Apr 20 '20 at 07:49
  • @FelixG I actually would. The important thing is not to suggest `{0}` as a _magic formula_ but to explain its ratio, so that the OP will be now on able to use it in the correct way. IMHO. – Roberto Caboni Apr 20 '20 at 07:51
  • 1
    @RobertoCaboni that's a valid point. It's just that i have seen code where a partial initializer like {1} was used, accompanied by a comment like "initialize array to 1" (and i'm talking about production code here). So i personally avoid this style of initializer, because the person coming after me might misunderstand it. – Felix G Apr 20 '20 at 07:56
  • @RobertoCaboni: The C standard guarantees that `0 == NULL` evaluates to true (1), because `0` meets the definition of a *null pointer constant*. It does not guarantee that a null pointer is represented with zero bits or that, after `int x = 0;`, `x == NULL` evaluates to true. – Eric Postpischil Apr 20 '20 at 10:43
  • @EricPostpischil That's was I was trying to write. In a awful way, apparently.. :) – Roberto Caboni Apr 20 '20 at 10:46
  • @user3386109, sorry you are quite correct, my mistake. – SPlatten Apr 20 '20 at 11:33

2 Answers2

5

The curly braces, { ... } are used for array initialization. When you declare an array, you can initialize its elements with syntax like this:

int a[3] = {1, 2, 3};

which sets the three members to, respectively, a[0] = 1, a[1] = 2 and a[2] = 3.

If the list contains less values than the array has elements, then all remaining elements are initialized to zero. From the link given above:

All array elements that are not initialized explicitly are initialized implicitly the same way as objects that have static storage duration.

Your pointer array has 10 elements but there is only one value in the initializer list, so all others are set to zero (as is the first element, explicitly).

Your use of NULL is actually not, in itself, the problem, as you could write (more clearly, IMHO):

struct Node *Bucket[10] = {NULL, };

as the NULL macro is generally defined like this:

#define NULL ((void *)0)

Note: The trailing comma I provided in the initializer list is otional but (again, IMHO) makes it clear(er) that you know there are more elements in the array, and that you are knowingly using the rule of 'implicit initialization to zero'. See here for a discussion: History of trailing comma in programming language grammars.

Feel free to ask for further clarification and/or explanation.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
  • 1
    Is that comma in `{NULL, }` a typo o some synthax I don't know? Furthermore, In order ot complete your answer (and get also my UV ;) ), I suggest you to explain also `{0}` initializer. – Roberto Caboni Apr 20 '20 at 07:53
  • 1
    @RobertoCaboni See edit (on the trailing comma). But I'm not sure what you mean by '"explain also `{0}` initializer" ... I thought I'd done that. – Adrian Mole Apr 20 '20 at 08:15
  • Bucket[] points to a location where there are 10 pointer of type struct Node * why are we making all of them NULL and not directly making Bucket as NULL and also what causes segmentation fault when we don't use NULL. – Utkarsh Singh Apr 20 '20 at 08:15
  • @UtkarshSingh `Bucket` is an array declared in automatic storage; referring to an array without a `[]` subscript is, effectively, referring to the *address* of the first element; this is determined by the compiler, from your code, and *cannot* be reassigned. – Adrian Mole Apr 20 '20 at 08:18
  • @UtkarshSingh You don't show how you use your `Bucket` array but, most likely, there is some code later on that checks for a 'valid' address in each array element before using it; typically, this would check for a non-NULL value, like: `if (Bucket[n] != NULL) { ...`; without the initialization, your array will be filled with arbitrary, unknown values. – Adrian Mole Apr 20 '20 at 08:20
  • @AdrianMole I have pasted my code , can you please help me with it. – Utkarsh Singh Apr 20 '20 at 08:26
  • Ok, now it is clear that the trailing comma wasn't a typo. Talking about the initializer, you actually provided an explanation; and I appreciate how it is somewhat completed by the other answer. Thank you. – Roberto Caboni Apr 20 '20 at 08:27
  • @UtkarshSingh The line `while( Bucket[j] )` in your code is checking for a non-NULL value, before executing the code in the loop - and see my previous comment. (Note, it is not normally considered appropriate to make major edits to a question *after* answers have been posted.) – Adrian Mole Apr 20 '20 at 08:28
  • @UtkarshSingh, don't edit too much a question after you have received several answers! You might invalidate them! Ask another question, instead! (and rollback the question to its previous status) – Roberto Caboni Apr 20 '20 at 08:29
3

According to The C programming Language By Brian W. Kernighan and Dennis M. Ritchie, Section 4.9 Initialization: "There is no way to specify repetition of an initializer, nor to initialize an element in the middle of an array without supplying all the preceding values as well." These authors are the authority to define what is allowed in C.

So the correct solution seems to be:

struct Node *Bucket[10] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};

But... according to the same authors: "The symbolic constant NULL is often used in place of zero, as a mnemonic to indicate more clearly that this is a special value for a pointer. NULL is defined in <stdio.h>." (See Section: 5.4 Address Arithmetic)

So, the teacher is right when he proposes to initialize as:

struct Node *Bucket[10] = {0};

because "if there are fewer initializers for an array than the specified size, the others will be zero for external, static and automatic variables." (See Section: 4.9 Initialization)

Pierre François
  • 5,850
  • 1
  • 17
  • 38
  • K&R originated C but are not authorities on what C is currently. The ISO/IEC C standard is widely accepted as the specification of C to use. Modern C includes designated initializers that can be used to initialize arbitrary elements, as in `int x[10] = { [7] = 35; };`. – Eric Postpischil Apr 20 '20 at 10:48