简体   繁体   中英

Casual value of a not initialized pointer to pointer

When I define a pointer without initializing it:

int *pi;

it points to a random part of the memory.

What happens when I define a pointer to pointer without initializing it?

int **ppi;

Where does it point? It should points to another pointer, but I didn't define it so maybe it points to a random part of the memory? If possible, could you show the difference with an example please?

To make it clear consider the following declaration

T *ptr;

where T is some type specifier. If the declared variable ptr has automatic storage duration then the pointer is initialized neither explicitly nor implicitly.

So the pointer has an indeterminate value.

T can be any type. You can define T as for example

typedef int T;

or

typedef int *T;

Pointers are scalar objects. Thus in this declaration

typedef int *T;
T *ptr;

the pointer ptr has indeterminate value the same way as in the declaration

typedef int T;
T *ptr;

Any local variable that isn't initialized contains an indeterminate value. Regardless of type. There's no obvious difference here between for example an uninitialized int , int* or int** .

However, there is a rule in C saying that if you don't access the address of such an uninitialized local variable, but use its value, you invoke undefined behavior - meaning a bug, possibly a crash etc. The rationale is likely that such variables may be allocated in registers and not have an addressable memory location. See https://stackoverflow.com/a/40674888/584518 for details.

So these examples below are all bad and wrong, since the address of the local variables themselves are never used:

{
  int i;
  int* ip;
  int** ipp;
  printf("%d\n, i);          // undefined behavior
  printf("%p\n, (void*)ip);  // undefined behavior
  printf("%p\n, (void*)ipp); // undefined behavior
}

However, if you take the address of a variable somewhere, C is less strict. In such a case you end up with the variable getting an indeterminate value , which means that it could contain anything and the value might not be consistent if you access it multiple times. This could be a "random address" in case of pointers, but not necessarily so.

An indeterminate value may be what's known as a "trap representation", a forbidden binary sequence for that type. In such cases, accessing the variable (read or write) invokes undefined behavior. This isn't likely to happen for plain int unless you have a very exotic system that is not using 2's complement - because in standard 2's complement systems, all value combinations of an int are valid and there are no padding bits, negative zero etc.

Example (assuming 2's complement):

{
  int i;
  int* ip = &i;
  printf("%d\n", *ip);  // unspecified behavior, might print anything
}

Unspecified behavior meaning that the compiler need not document the behavior. You can get any kind of output and it need not be consistent. But at least the program won't crash & burn as might happen in the case of undefined behavior .

But trap representations is more likely to be a thing for pointer variables. A specific CPU could have a restricted address space or at the low level initialization, the MMU could be set to have certain regions as virtual, some regions to only contain data or some regions to only contain code etc. It might be possible that such a CPU generates a hardware exception even when you read an invalid address value into an index register. It is certainly very likely that it does so if you attempt to access memory through an invalid address.

For example, the MMU might block runaway code which tries to execute code from the data segment of the memory, or to access the contents of the code memory as if it was data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM