2

I was playing around with C on my Mac OS X (version 10.6.8); this is the small program to test what happens when you declare and int but don't initialize it:

#include <stdio.h>

int main() {
    int a;
    printf("\n%d\n\n", a); 
}

When I do gcc -std=c99 test.c; ./a.out, I get a predictable result: the max for an unsigned int (32767). However, something strange happens when I use the -o using gcc. When I do gcc -std=c99 test.c -o test.out; ./test.out I get something else: 0.

It doesn't matter what I name the file or how I compile it, I have figured out. If the name is not a.out, then I get 0. When the name is a.out I get either the largest uint type or some other larger number.

Contrary to some thoughts below, the number is semi-random (mostly largest uint but sometimes a larger number) only when the compiled file is a.out which is really weird. It could just be my computer; or, perhaps, I have luckily - or unluckily - received the same results 30 times in a row.

dylnmc
  • 3,810
  • 4
  • 26
  • 42
  • 3
    Undefined behavior is allowed to be nasal daemons. – Patrick Collins Dec 08 '14 at 23:29
  • Any reason why it should differ when the file name changes is beyond me though. – dylnmc Dec 08 '14 at 23:31
  • You even cannot rely on it doing the same thing when starting the programme several times without recompiling. Undefined behaviour need not be consistent – mafso Dec 08 '14 at 23:32
  • Um thanks for the downvotes? You know people don't know everything about everything. – dylnmc Dec 08 '14 at 23:32
  • No, it seems pretty consistent even after recompiling... maybe I got lucky a couple times... let me check again – dylnmc Dec 08 '14 at 23:33
  • Hm. I guess you're right. I just got `1606422610`. – dylnmc Dec 08 '14 at 23:36
  • Should I not have asked this question? Would anyone care to explain why they are down voting? I'm not really mad - more baffled. Do people want others to remain ignorant? – dylnmc Dec 08 '14 at 23:37
  • You could use a debugger or other print statements to inspect a larger area of memory around where `a` is stored and see if you recognize what's there. A possible explanation might be stack variables used by the code which sets up the `argv` array or other startup environment. – M.M Dec 08 '14 at 23:38
  • It may depend on the programmes you invoke in between. It may rely on anything. It's sometimes interesting to understand the result of some UB, but I don't expect anything interesting here. If you want some details, we need the generated assembly. – mafso Dec 08 '14 at 23:38
  • BTW 32767 isn't the max for an unsigned int. – M.M Dec 08 '14 at 23:39
  • 4
    I think it's pretty interesting. But to understand where those values come from you'll need to debug the code that runs **before main**. And that code is different depending on which OS you are on. What you are seeing as the value of `a` is what what left on the stack prior to `main` running. So the code that loads and sets up your program to run must have a difference depending on the program name. This is somewhat understandable since argv[0] is your program name and it will differ between runs. – JS1 Dec 08 '14 at 23:40
  • 1
    I don’t know why the downvote brigade showed up. It’s a good question, but not necessarily answerable. Undefined behavior can blow up your computer and rain down meteors from orbit if it wants to. – yellowantphil Dec 08 '14 at 23:40
  • 1
    I rolled back that edit. If at all, this question should be deleted, not defaced. But I think it might be improved with platform/compiler details and the assembler output, if you're interested in what happens under the hood. In the scope of C itself, this question isn't answerable. – mafso Dec 08 '14 at 23:42
  • @mafso: Really? I just answered it. – Keith Thompson Dec 08 '14 at 23:48
  • 1
    In C11, if we modify the code to take the address of `a` at some point, and it is known that the system has no trap representation, then the program does not have undefined behaviour. (Instead the value is unspecified). [Ref](http://stackoverflow.com/questions/25074180/is-aa-or-a-a-undefined-behaviour-if-a-is-not-initialized/25074258#25074258) . If you write `&a;` and still get the observed behaviour, it'd improve the question because you no longer invoke undefined behaviour. – M.M Dec 08 '14 at 23:56
  • @KeithThompson: Sure it can be answered (you just did!); OP struggled a little with the downvotes, so I tried to give some ideas for improvement, because I thought the question could be kept (though it's probably also a duplicate). Questions about a certain result of some UB are often not welcomed here without some details about the platform. (What I agree with in general, but not with the many downvotes such questions often receive.) – mafso Dec 09 '14 at 00:01
  • @MattMcNabb: I wouldn't expect a compiler to honour `&a;`. And I wouldn't expect a compiler to really behave undefined with or without it. (What is observed here is totally explainable with unspecified behaviour.) – mafso Dec 09 '14 at 00:06
  • @mafso my point is that it can be turned into a question that does not have UB, which is a good thing – M.M Dec 09 '14 at 00:10
  • Well, this is perhaps the most interesting behavior I have witnessed after asking a question on stackoverflow. I ask a simple yet - to me - strange question about C, I get a lot of downvotes, I come back and somehow I have broken even with my "votes" - which, honestly I care about to some degree because it allows me to comment and help others once I am above a certain "level." I'm not extremely experienced and this was hard to type into the Google search engine and find a source that explains what was going on. So thanks. – dylnmc Dec 09 '14 at 00:15
  • in ALL cases, your printing what ever happens to be on the stack at the int sized bytes at the 'a' variable location. – user3629249 Dec 09 '14 at 00:20
  • @MattMcNabb: A question that doesn't have UB would be a completely different question. Without undefined behavior, using or not using the `-o` option wouldn't change the program's output, and there would be nothing to ask about. – Keith Thompson Dec 09 '14 at 00:24
  • @user3629249 That's what I would assume, too. That is why it seems strange that it changes with the file name. – dylnmc Dec 09 '14 at 00:25
  • A very minor point, not relevant to your question: `int main()` should be `int main(void)`. Using `int main()` is almost certainly harmless, but it's an old-style function definition, and it depends on a feature that's been declared obsolescent. – Keith Thompson Dec 09 '14 at 01:13
  • @KeithThompson I conjecture that the same behaviour may occur even when the program does not have UB (merely unspecified behaviour) , it's worth trying and it would remove any distracting issues such as "UB means nasal demons" from what OP is really asking about – M.M Dec 09 '14 at 01:41
  • @MattMcNabb: Do you have an example in mind? – Keith Thompson Dec 09 '14 at 02:35
  • @KeithThompson yes, add `&a;` after `int a;`, and stipulate that we're on a system with no trap representations, and using C11 – M.M Dec 09 '14 at 03:16

1 Answers1

5

The output of your program is meaningless, and is likely to be inconsistent from one run to the next.

Strictly speaking, your program has undefined behavior, since it reads the value of an object that has never been initialized or assigned to. That means that the C standard says nothing at all about what it will do. (The standard joke is that it can, in principle, make demons fly out of your nose; of course that's not going to happen, but if it did it wouldn't violate the rules of the C language.)

In practice, what's likely to happen is that the value printed will be whatever garbage happened to be in memory when your program started running. Using or not using -o when you compile the program may or may not have any effect. Likewise, the phase of the moon at link time may or may not have any effect.

People sometimes refer to this kind of garbage as "random", but that word has a specific statistical meaning. The value printed is arbitrary. It might happen to be the same every time you run the program, it might sometimes be 0, or anything else.

You wrote:

I get a predictable result: the max for an unsigned int (32767).

In fact, the maximum value for an unsigned int is at least 65535, and is more likely to be 4294967295. (See UINT_MAX, defined in <limits.h> for the actual value for your system). But that doesn't really matter; 32767 is as valid as any other garbage value.

(If you have defined a at file scope, or with the static keyword, it would have a well-defined initial value of 0. "Automatic" variables (those defined inside a function definition without the static keyword) have no defined initial value.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631