-4

suppose we have the following declarations in C :

double d[25], * p;
int * t;
char * c;

How can we explaine the following printf() results ?

printf("d : %x\t",d);
printf("p : %x\t",p);
printf("t : %x\t",t);
printf("c : %x\t",c);

which print the ligne :

d : 62fd30    p : 1    t : 0    c : 39    

We can clairly see the memory adress of d but both p, t and c don't look like adresses. I used to think that a uninitialized pointer takes the Null value after its declaration. Am I wrong? how can we explain these results?

Simo
  • 155
  • 3
  • 12

3 Answers3

5

All automatic (non-static local) variables will by default be uninitialized with an indeterminate value (that can seem like random or garbage). It doesn't matter if the variable is a pointer or not.

Also, just reading the value of an uninitialized pointer isn't automatically UB (in C), but dereferencing an uninitialized pointer definitely is.

However, as mentioned in one comment, you need to use "%p" to print pointers (technically they need to be casted to void * as well). Mismatching printf format specifier and argument type do lead to UB.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
3

You cannot assume any pointer will be zero-initialized after declaration - C standard does not imply anything at that point. Same goes with other types of values. This is why it is a good practice to set a value of a variable upon declaration, like:

int * t = NULL;

Some compilers do zero-initialize variables, but this is tool-specific feature.

Diodacus
  • 663
  • 3
  • 8
  • 2
    I would say, it is only good practice to initialize it, if there is a chance that this initialization value is indeed used somewhere. Otherwise, it is ugly code. – Ctx Mar 21 '19 at 13:38
3

I used to think that a uninitialized pointer takes the Null value after its declaration. Am I wrong?

Yes, your assumption are incorrect. An uninitialized pointer declared with automatic storage always contains garbage or junk data i.e not a valid address, hence its better to initialize with NULL at first while declaring. For e.g

double *d = NULL;
/* some processing */
if(d == NULL) {
  /* @TODO error handling. Not allowed to de-reference NULL pointer */
}

Here

double d[25];
printf("d : %x\t",d);

d is an array of 25 double's & array name itself address, while printing d using %x causes undefined behavior, even your compiler could have warned you like this

main.c:5:19: warning: format specifies type 'unsigned int'but the argument has type 'double *' [-Wformat]

But you seems to ignore compiler warnings, one shouldn't. Always compiler your code with minimal flags like -Wall. For e.g

gcc -Wall -Werror -Wpedantic test.c

To print array name, use %p format specifier. for e.g

double d[25];
printf("Array d : %p\t",(void*)d);

Similarly with int pointer t and char pointer c, use %p format specifier instead of %x. Also don't keep any uninitialized pointer in your code.

int * t; /* initialized with valid address else 
            dereferencing uninitialized pointer causes UB */
printf("t : %p\n",(void*)t);
Achal
  • 11,821
  • 2
  • 15
  • 37