Home > Back-end >  How to assign to to an uninitialized pointer variable in a function?
How to assign to to an uninitialized pointer variable in a function?

Time:04-21

I would like to make this program legal and correct:

#include <assert.h>                                                             
#include <stdlib.h>                                                             
                                                                                
#define SOME_INT 5                                                              
                                                                                
                                                                                
void assign_to_x(??) {                                                     
     ???                                                             
}                                                                               
                                                                                
                                                                                
void main(void){                                                                
    int *x;                                                                     
    assign_to_x(?);                                                            
    assert(*x == SOME_INT);                                                     
    // potential cleanup                                                                 
}     

Initially x in pointing to some location such that I cannot dereference it without causing undefined behavior. So in the assign_to_x I cannot just put SOME_INT into the location it's pointing. What are my options then?

One option I see is:

void assign_to_x(int **x) {                                                     
    *x = (int *)malloc(sizeof(int *));                                          
    **x = SOME_INT;                                                             
}                                                                               
                                                                                
                                                                                
void main(void){                                                                
    int *x;                                                                     
    assign_to_x(&x);                                                            
    assert(*x == SOME_INT);                                                     
    free(x);                                                                    
}   

This however seems to be an overkill.

Another thing I can think of is:

void assign_to_x(int **x) {
    static int y = SOME_INT;
    *x = &y;
}


void main(void){
    int *x;
    assign_to_x(&x);
    assert(*x == SOME_INT);
}

But is it actually valid? Is there a different, canonical option?

CodePudding user response:

If the static int solution satisfies your program’s needs, then the solution with that is okay. It is important to be aware that if the program is later modified so that it needs multiple instances of *x, say because its is redesigned to use multiple threads for some work, then the static int solution will break unless it is modified too.

The malloc solution has a bug; sizeof(int *) should have the size of an int, not the size of a pointer to an int.

Otherwise, the malloc solution is not over-engineered except that the cast is not needed in C; *x = (int *)malloc(sizeof(int)); can be *x = malloc(sizeof **x);. This is allowed because C allows the void * type that malloc returns to be implicitly converted to int *. It is preferred because if a programmer accidentally fails to declare malloc (as by including <stdlib.h>), it will allow the compiler to produce a warning. (With the cast, some compilers will generate a default declaration for malloc with an int return type, due to the history of C development, and then the explicit cast will convert this int to int *. Without the cast, the compiler will issue a warning for the improper assignment of int to int *.)

It is also nicer to use sizeof **x rather than sizeof(int *) because then, if x is later changed to some other type, such as double **x, the sizeof does not need to be changed too; it automatically follows the type of x.

  • Related