1

I am learning now C, and these days I am studying pointers and I just come with a question!

int *ptr;       //declare the ptr
ptr = &var;     //init the ptr with the address of the variable var

with these lines, I created a pointer and I linked the ptr with a variable. My question is this, when I declare a pointer int *ptr; and I don't initialize it with an address, this pointer where it points?

yaylitzis
  • 5,354
  • 17
  • 62
  • 107
  • 4
    The value is indeterminate, and that isn't exclusive to pointers. `int a;` What's the value of `a` ? Hmm.... – WhozCraig Oct 27 '13 at 17:34
  • @WhozCraig: For want of a better answer elsewhere I've posted one here. – Kerrek SB Oct 27 '13 at 18:08
  • @KerrekSB the one I linked was the best I could find, and yours is far better, especially in regards to this question. +1 for that, sir. – WhozCraig Oct 27 '13 at 18:14

6 Answers6

2

It is just like any other uninitialized local variable -- it is undefined where it points or what value it contains, and you are not allowed to use it (e.g., dereference it) until it is initialized. As stated in @WhozCraig's comment, almost all other operations are forbidden as well (using the pointer's value at all, including arithmetic and comparisons). Uninitialized non-pointer variables (even those with simple types such as ints) cannot be used for any operations that access their values, either.

Jeremiah Willcock
  • 30,161
  • 7
  • 76
  • 78
  • 2
    Its deeper than that. Even *evaluating* it (i.e. `int *p1, *p2 = p1;` or `int *ptr; if (ptr) {...}`) is undefined behavior. It isn't just limited to dereferencing. – WhozCraig Oct 27 '13 at 17:36
  • 1
    It's worse. The value is indeterminate and you can't almost anything with it. Not only dereference, but other operations will trigger UB. – zch Oct 27 '13 at 17:36
  • @WhozCraig: You should make that an answer. This one is the only answer that isn't outright off-topic or misleading, and it's still far short of the truth. – Kerrek SB Oct 27 '13 at 17:37
  • 2
    @KerrekSB for a minute I though your last sentence was in reference to *my* comment, not *this* answer. This has to be a duplicate somewhere. I would rather find it and send this on its merry way. [This one seems promising](http://stackoverflow.com/questions/3101896/c-why-do-unassigned-pointers-point-to-unpredictable-memory-and-not-point-to-nul). still looking for others. – WhozCraig Oct 27 '13 at 17:39
  • @WhozCraig: I have now updated my answer based on your comments. – Jeremiah Willcock Oct 27 '13 at 17:42
  • @JeremiahWillcock Is isn't just "many" operations; its *any* operations that utilizes the value. Because the value is undefined, so is *any* usage therein. And its an interesting side-note that there exists platforms that equate indeterminate pointer values, including dangling pointers and uninitialized pointers, to platform-NULL (OS/400 is one such beast). – WhozCraig Oct 27 '13 at 17:48
  • @WhozCraig: Sorry for the scare :-) I'm not sure about that answer, either. I find all this talk about NULL distracting and misleading. The simple fact is that you're not allowed to evaluate (in the sense of lvalue-to-rvalue conversion) an uninitialized variable, nothing more, nothing less... – Kerrek SB Oct 27 '13 at 17:49
  • @WhozCraig: What do you think of the current version (updated again)? – Jeremiah Willcock Oct 27 '13 at 17:52
  • @KerrekSB Exactly. the rest is just fodder. The subject is overtly applicable to anything that has no determinate value, either assigned by code, or defined by the standard as having initial state. – WhozCraig Oct 27 '13 at 17:55
  • @JeremiahWillcock It is considerably better. The *value* is the stress-point. Using the variable in a non-eval usage is fine. For example, by-address (i.e. passing it as `&var` to a function to initialize it in some way) is ok. There simply must be no eval until a determinate value is stored. If such an eval exists, its undefined behavior. – WhozCraig Oct 27 '13 at 18:02
  • @wildplasser how is the evaluation-usage of *either* of those *not* covered by the blanket statement that has been the mantra of every comment I've made on this question? Using the *value* of *any* variable without it being initialized to a determinate state is undefined behavior. Do you think that is somehow not covering your `if`-comparison? – WhozCraig Oct 27 '13 at 18:10
2

In C, variables are generally not initialized unless you specifically say so:

int a;                 // not initialized
int b = 1;             // initialized

int arr[10];           // not initialized
int brr[4] =  { 1 };   // initialized as { 1, 0, 0, 0 }

void * p;              // not initialized
void * q = &a;         // initialized

(There are exceptions for variables with static or thread-local storage, which are always zero-initialized.)

It is not allowed to try and get at the value of an uninitialized variable. The only thing you can do with an uninitialized variable is assign to it, which does not access its current value, but only assigns a new value to it. Before initialization or assignment, the current value of a variable is "indeterminate" and you must not attempt to access it. Doing so results in undefined behaviour.

This is true for all variables, but in particular it applies to your pointer variable. It simply has no meaningful value until you assign one.

void * p;              // not initialized

if (p) { /*...*/ }     // undefined behaviour!
printf("%p\n", p);     // undefined behaviour!

p = &a;                // now p has a well-defined value

The technical term for the action that is causing undefined behaviour is the so-called "lvalue conversion". That is the moment in which you take a named variable (an "lvalue") and use its content. E.g. C11, 6.3.2.1/2 says:

If the lvalue designates an object of automatic storage duration [...] and that object is uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • There is a curious caveat in C11 which I've hidden in the ellipsis: The object must be such that it could have had `register` storage, i.e. never have its address taken. It sounds like if you take the address of an object (like my `a` above), it is no longer undefined behaviour to use it in lvalue conversion, *even if* its value is indeterminate. Also note how this is rather different in C++. – Kerrek SB Oct 27 '13 at 18:07
  • The standard citation is awesome, and it hopefully hits home with anyone that reads this. – WhozCraig Oct 27 '13 at 18:13
1

Actually, as it has been stated in almost all answers so far, the pointer's value is unknown and consists of the contents of the memory at that location when it was allocated.

Contrary to what some answers state though, noone and nothing is going to forbid you dereferencing it, or doing any kind of operation with this pointer.

As a result, using such a pointer will produce any kind of unpredictable results. It is not only best practice but a requirement for producing less buggy code, to initialize a pointer on declaration to something, even if that something is, simply, NULL.

ThunderGr
  • 2,297
  • 29
  • 20
  • @Martin James Please clarify. In your code, nothing forbids you to use an uninitialized pointer. And the compiler will compile it fine. – ThunderGr Oct 27 '13 at 18:02
  • 2
    "..may produce any kind of unpredictable results" Indeterminate variable usage isn't a "may" produce scenario. By the definition of undefined-behaviour, it *will* produce unpredictable results. And as far as something preventing you from using undefined behavior in your program, well of course no such thing exists in C. There's an unofficial pattern name for such code: its called "crappy code", though I often refer to it as "severance code". – WhozCraig Oct 27 '13 at 18:06
  • @WhozCraig I do mention that in my answer(about the crappy code), in lighter words. As for the "may", it is just a figure of speech and what you define as "unpredictable result". It *can* happen to point at a valid location and an int *p; may even return a value. This is even worst than causing a seg-fault, as it may make it appear as if the code works. But, you are right, "may" is confusing. I am editing it, now. – ThunderGr Oct 27 '13 at 18:12
0

It points to a random memory location. Dereferencing such a pointer usually leads to a segfault.

Igor Popov
  • 2,588
  • 17
  • 20
0

In this case, it will point anywhere. You don't know. The contents of the pointer will be whatever was at the memory location before. So this is very dangerous and should be avoided. You should always init a pointer with NULL, then it will point to "nothing" in a defined way.

PMF
  • 14,535
  • 3
  • 23
  • 49
0

Like any other non-static variable in C, it's not initialized automatically. It contains whatever junk data was in the memory slot, and so deferencing it before assigning a proper value to it is likely to be a bad idea.

kviiri
  • 3,282
  • 1
  • 21
  • 30