0

What is the difference between int variable; and int variable = 0;? I've seen them both used, and, if I recall correctly, by the same author in the same file.

As far as I can tell, they're the same:

$ cat integers.c
#include <stdio.h>

int main(void) {
    int patty;
    int tim = 0;
    printf("Patty: %d\nTim: %d\n", patty, tim);
}
$ gcc integers.c -o integers
$ ./integers
Patty: 0
Tim: 0

This goes for other variable types, too: what is the difference between char *variable; and char *variable = NULL;?

Billy
  • 1,177
  • 2
  • 15
  • 35
  • 2
    Attempting to access an indeterminate value is *Undefined Behavior* - Boom! the defined operation of your code ceases at `int tim = 0;` – David C. Rankin Jul 14 '18 at 03:26
  • 1
    @DavidC.Rankin's point should be strong enough; a program with undefined behavior can do whatever the compiler wants, which often isn't what you want. In practice, I expect that if you try doing this deeper in the call stack when you have already called other functions and I expect you'll see it can take on any variable. But the compiler could do other things as well, and there's a reasonable chance that different compilers do different things. – Daniel H Jul 14 '18 at 03:33
  • undefined behavior is undefined. – Stargateur Jul 14 '18 at 03:56

3 Answers3

4

As far as I can tell, they're the same

No they are not. Accessing patty is undefined beavior because it is not initialized.You just happen to get same result. If patty were global, then it would have been default initialized(0).

Gaurav Sehgal
  • 7,422
  • 2
  • 18
  • 34
  • 2
    Behavior is *undefined* -- anything can happen from appearing to work normally to SEGFAULT or anything in between. – David C. Rankin Jul 14 '18 at 03:27
  • @DavidC.Rankin Yes, but what *did* happen is that the variable was initialized to 0. That might not happen on your compiler, and it probably wouldn't happen in similar code called slightly differently, but since the OP actually did run this code there is an actual well-defined result that happened. It just wasn't defined by the C standard. – Daniel H Jul 14 '18 at 03:29
  • 3
    That's not quite true. The indeterminate memory for the `4-bytes` referenced by `patty` just happened to be zero, nothing in the standard provides that they be initialized in any particular way. Instead, the standard defines the access of an indeterminate value as *Undefined Behavior* -- nothing more. – David C. Rankin Jul 14 '18 at 03:33
  • @DavidC.Rankin The standard doesn't provide that, but I'm guessing that the compiler's output program is such that it used whatever four bytes (probably; `sizeof int` might not be 4) happened to be at the right place on the stack, and the OS's program loading logic often gives a zeroed-out stack on startup. Undefined behavior may be where the standard stops saying anything, but it does not literally end the world so *something* still happens. In this case, that something is reading four bytes that were, for some reason, all zeroes. – Daniel H Jul 14 '18 at 03:36
  • Yes, yes, I agree there. It just tells you the memory in that region happened to have that number of bytes zero (for whatever reason). I'm not sure that is something you can attribute to the compiler, though they are free to implement storage for locals however they like. – David C. Rankin Jul 14 '18 at 03:53
  • 2
    @DanielH The standard is very clear on this. Reading a variable that has not been initialized is undefined behavior. End of discussion. The fact that it behaves in a certain way on compiler A has no bearing on what will happen on compiler B, or even with a later version of compiler A. "The worst possible result of undefined behavior is for it to do what you expect." – dgnuff Jul 14 '18 at 03:59
  • @dgnuff I completely agree that it could, and probably will, do different things in different cases; this isn't just for a different compiler or version, but the same compiler in a more realistic program. – Daniel H Jul 14 '18 at 04:23
  • 1
    It doesn't matter that it's for the same compiler, twenty minutes later. It's undefined behavior, so you have no guarantees at all that it'll do what you're expecting. I know this sounds very language lawyerish, but it really is a bad idea to ever assume anything about undefined behavior. It could be that the result is due to it leaving the memory untouched but that the compiler just happens to dump a large bunch of zeroes in memory that happen to be where your variable lands. So it works in test. Then you use it in production, after running Excel instead of the compiler, and now it breaks. – dgnuff Jul 14 '18 at 05:04
  • @DavidC.Rankin: The C standard does not define the access of an indeterminate value to be undefined behavior. It defines the access of an object of automatic storage duration that could have been declared to be `register` taken to be undefined behavior. Accessing an array element, for example, that has not been initialized does not necessary cause undefined behavior, since it could not have been declared `register`. – Eric Postpischil Jul 14 '18 at 10:45
  • @dgnuff: The standard is not clear on this, as the rule you state is not correct, and the standard says multiple things about this in different places and has been subject to question and interpretation. There is no general rule that reading an object that has not been initialized is undefined behavior. There are rules about trap values and about accessing the value of an object of automatic storage duration that is uninitialized and could have been declared `register`. But reading an uninitialized element of an array of `unsigned char`, for example, does not cause undefined behavior. – Eric Postpischil Jul 14 '18 at 10:49
  • @EricPostpischil I know exactly how it is phrased in the standard and how utterly bewildering the *"could have been declared `register`"* language is to someone who at this point doesn't see the difference between `int patty; int tim = 0;`. It is far more effective from a learning standpoint to know you cannot use or access values with an indeterminate value, than it is to the debate when or when not a variable *"could have been declared `register`"* . – David C. Rankin Jul 15 '18 at 04:34
  • @DavidC.Rankin: i am aware of the difficulty of conveying complex specifications to learners, but I do not believe the complexity, difficulty of learning, or a student’s potential bewilderment justifies making false statements. If behavior is not undefined over a set of circumstances, we should not falsely state that it is undefined. Doing so creates false beliefs that are harder to undo later than to teach correctly in the first place. With a little effort, true statements can be crafted that are suitable for teaching without immediately delving into the complexities. – Eric Postpischil Jul 15 '18 at 10:14
3

The storage duration of both variable patty and tim is automatic.

Variable patty and tim are same in terms of storage duration but results may be different when you try to access them because one is initialized and other is not and accessing an uninitialized object with automatic storage duration is undefined behavior:

    int patty;   //Uninitialized
    int tim = 0; //Initialized

From C Standards#6.7.9p10 [Initialization]

If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate.

From C Standards#J.2 [Undefined behavior]

The value of an object with automatic storage duration is used while it is indeterminate (6.2.4, 6.7.9, 6.8).

An undefined behavior includes it may execute incorrectly (either crashing or silently generating incorrect results), or it may fortuitously do exactly what the programmer intended.

Though you are getting the value of patty and tim variable same in the output but certainly they are not same.

$ ./integers
Patty: 0    <----- indeterminate value
Tim: 0      <----- value that tim initialized with
H.S.
  • 11,654
  • 2
  • 15
  • 32
  • You are a bit crazy about undefined behavior. No segfault or crash may occur in this case. It just may print garbage value, that's all. – purec Jul 14 '18 at 08:57
  • @H.S.: Annex J is non-normative and is an incomplete summary. The actual rule about using the indeterminate value of an object with automatic storage duration is in 6.3.2.1, and it contains the additional criterion that the object could have been declared with `register`. While this does not alter the specific case OP uses as an example, it means that, using the indeterminate value of an `unsigned char` in an array or whose address has been otherwise taken is not subject to the rule that makes it undefined behavior. – Eric Postpischil Jul 14 '18 at 10:53
  • @purec: In this specific case, a segmentation fault or crash may occur. That is because C 2011 [draft N1570] 6.3.2.1 2 says “If the lvalue designates an object of automatic storage duration that could have been declared with the **register** storage class (never had its address taken), 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.” – Eric Postpischil Jul 14 '18 at 10:57
  • @Eric Postpischil, It is hard to say what this manual is about. I can't see why printf() may fail printing uninitialized register value. I tried to produce segfault but unsuccessfully. – purec Jul 16 '18 at 07:56
  • @purec: [The meaning and history of that passage in the C standard is established.](https://stackoverflow.com/questions/11962457/why-is-using-an-uninitialized-variable-undefined-behavior) It was originally added to support the NaT bit of Itanium processors but is used by compilers generally to license optimizations. You should not expect to usemit to produce a crash with simple code, but it can license a C compiler to fold code paths that use uninitialized objects into other code paths during optimization, which leads to undefined behavior in complicated ways. – Eric Postpischil Jul 16 '18 at 10:41
  • @purec: The simple fact is that that passage in the C standard means what it says: Using the value of an uninitialized object of automatic storage duration that could have been declared `register` has undefined behavior and therefore may crash. – Eric Postpischil Jul 16 '18 at 10:43
1

Actually they aren't the same an unassigned variable may have any garbage value but assigned variable has defined value for instance int h; int j=6; if you print these you wont get always 0 for h but you will definitely get 6 for j variable

  • 1
    Undefined behavior is different from an indeterminate value. You might not get just a variable access of a garbage value (although, given current compilers, that's probably the most likely result in practice); you could get anything else depending on what the compiler thought made sense. Other somewhat-plausible answers are "the compiler realizes this is UB and decides the entire code branch will never happen, and optimizes out whatever `if` statement gets you there" and "There is no space allocated for the variable so you read invalid memory". But it could be anything. – Daniel H Jul 14 '18 at 04:26