tags:

views:

224

answers:

12

e.g. I'm usually compulsive obsessive and like to do

static int i = 0;
if (!i) i = var;

but

static int i;
if (!i) i = var;

would also work.

Why? Why can't it segfault so we can all be happy that undefined variables are evil and be concise about it?

Not even the compilers complain:(

This 'philosophy' of indecisiveness in C has made me do errors such as this:

strcat(<uninitialized>, <proper_string>))  //wrong!!1

strcpy(<uninitialized>, <proper_string>))  //nice
A: 

That's C, you cannot do much about it. The basic purpose of C is to be fast - a default initialization of the variable takes a few more CPU cycles and therefore you have to explicitly specify that you want to spend them. Because of this (and many other pitfalls) C is not considered good for those who don't know what they are doing :)

dark_charlie
A: 

It's to squeeze every last cycle out of your CPU. On a modern CPU of course not initializing a variable until the last millisecond is a totally trivial thing, but when C was designed, that was not necessarily the case.

DeadMG
It can still be a problem on systems C is used on. Embedded CPUs are not very fast. Some of them don't even have cache, so memory writes are expensive.
Zan Lynx
@Zan Lynx: It is sometimes useful to say "if (variableInEEPROM != desiredValue) EEPROM_WRITE(variableInEEPROM, desiredValue);" if one is using an EEPROM which can be read like ordinary memory. I know of no embedded-system compiler that allows direct assignments to variables stored in any type of memory that is much slower to write than to read.
supercat
A: 

That behavior is undefined. Stack variables are uninitialized, so your second example may work in your compiler on your platform that one time you ran it, but it probably won't in most cases.

Getting to your broader question, compile with -Wall and -pedantic and it may make you happier. Also, if you're going to be ocd about it, you may as well write if (i == 0) i = var;

p.s. Don't be ocd about it. Trust that variable initialization works or don't use it. With C99 you can declare your variables right before you use them.

Nathon
"if (i == 0)". hehe, nice.
Lela Dax
Semantically speaking, `0` is not the same as `False`.
Nathon
A: 

The C standard says the behavior of uninitialized auto variables is undefined. A particular C compiler may initialize all variables to zero (or pointers to null), but since this is undefined behavior you can't rely on it being the case for a compiler, or even any version of a particular compiler. In other words, always be explicit, and undefined means just that: The behavior is not defined and may vary from implementation to implementation.

-- Edit -- As pointed out, the particular question was about static variables, which have defined initialization behavior according to the standard. Although it's still good practice to always explicitly initialize variables, this answer is only relevant to auto variables which do not have defined behavior.

Benjamin Cutler
Uninitialized auto variables are undefined. Uninitialized global variables are reliably initialized to zero.
Darron
Global and static variables are guaranteed to be initialized to 0 by the C standard. Google says.
mvds
Amardeep
I missed the static part; this answer is irrelevant to the particular question. Thanks.
Benjamin Cutler
I think it's safe to assume that the OP's variable `i` was on the stack. It had an if block immediately following it.
Nathon
+1  A: 

In your example, i is not an undefined variable, it is an uninitialized variable. And C has good reasons for not producing an error in these cases. For instance, a variable may be uninitialized when it is defined but assigned a value before it is used, so it is not a semantic error to lack an initialization in the definition statement.

Not all uses of uninitialized variables can be checked at compile-time. You could suggest that the program check every access to every variable by performing a runtime check, but that requires incurring a runtime overhead for something that is not necessary if the programmer wrote the code correctly. That's against the philosophy of C. A similar argument applies to why automatically-allocated variables aren't initialized by default.

However, in cases where the use of a variable before being initialized can be detected at compile-time, most modern compilers will emit a warning about it, if you have your warning level turned up high enough (which you always should). So even though the standard does not require it, it's easy to get a helpful diagnostic about this sort of thing.

Edit: Your edit to your question makes it make no sense. If i is declared to be static then it is initialized -- to zero.

Tyler McHenry
The title is edited to say initialized instead of undefined, you're right. Er, why is a static variable initialized automatically? I don't remember that being true.
Lela Dax
Well, regardless of if you remember it, it is true. Variables with static storage duration are automatically initialized to zero.
Tyler McHenry
+1  A: 

It seems you don't understand something about C.

int i;

actually DOES define the variable in addition to declaring it. There is memory storage. There is just no initialization when in function scope.

int i=0;

declares, defines, and initializes the storage to 0.

if (!i)

is completely unnecessary before assigning a value to i. All it does is test the value of integer i (which may or may not be initialized to a specific value depending on which statement above you used).

It would only be useful if you did:

int *i = malloc(sizeof int);

because then i would be a pointer you are checking for validity.

Amardeep
You're right, I should have said initialization instead of definition. Also the example was meant to be static int i; not int i; (since the check was supposed to be there for a looping mechanism).QUESTION TITLE EDITED DUE TO THIS: s/defined/initialized
Lela Dax
Seems a misinformed downvoter visited. FYI - defined != initialized.
Amardeep
A: 

C simply gives you space, but it doesn't promise to know what is in that space. It is garbage data. An automatically added check in the compiler is possible, but that extends compile times. C is a powerful language, and as such you have the power to do anything and fall on your face at the same time. If you want something, you have to explicitly ask for it. Thus is the C philosophy.

Scott M.
A: 

Hey this behavior of C is compiler dependent. Some compilers assign default value to variable which is this case is zero(0).

And about the segmentation fault:

The segmentation fault occurs while accessing undefined memory location (that is not known to current program/process). Every integer variable is assigned the required memory when it is declared so there is no possibility of segmentation fault.

The segmentation fault generally occur for pointers when you don't allocate memory to the pointer. That is do not use malloc() or calloc().

SPatil
static variables are initialized to zero. Local variables are not.
Nyan
Simply wrong. Static variables are always zero-initialized if you do not initialize them. -1 for spreading ignorant misinformation about C.
R..
Who keeps upvoting **wrong** answers?!
R..
+1  A: 

This comes from C's "lightweight" and "concise" roots. Default initializing to zero bytes was free (for global variables). And why specify anything in source text when you know what the compiler is going to do?

Uninitialized auto variables can contain random data, and in that case your "if" statements are not only odd but don't reliably do what you desire.

Darron
A: 

Where is var defined?

The codepad compiler for C gives me the following error:

In function 'main': Line 4: error: 'var' undeclared (first use in this function) Line 4: error: (Each undeclared identifier is reported only once Line 4: error: for each function it appears in.)

for the code:

int main(void)
{
  static int i;
  if (!i) i = var;
  return 0;
}

If I define var as an int then the program compiles fine.

I am not really sure where your problem is. The program seems to be working fine. Segfault is not for causing your program to crash because you coded something that may be undefined in the language. The variable i is unitialized not undefined. You defined it as static int. Had you simply done:

int main(void)
{
  i = var;
  return 0;
}

Then it would most definately be undefined.

Your compiler should be throwing a warning because i isn't initialized to catch these sort of gotchas. It seems your if statement is sort of a catch for that warning, even if the compiler does not report it.

0A0D
`var` is obviously a demonstrative placeholder. Replace it with a numeric constant if you're trying to play along.
Nathon
'var' was just an example, it doesn't matter what it is.
Lela Dax
Thanks I got that
0A0D
+1  A: 

You said:

Why? Why can't it segfault so we can all be happy that undefined variables are evil and be concise about it?

A "segfault" or segmentation fault, is a term that is a throwback to segmented memory OSes. Segmentation was used to get around the fact that the size of the machine word was inadequate to address all of available memory. As such, it is a runtime error, not a compile time one.

C is really not that many steps up from assembly language. It just does what you tell it to do. When you define your int, a machine word's worth of memory is allocated. Period. That memory is in a particular state at runtime, whether you initialize it specifically or leave it to randomness.

Buggieboy
+1  A: 

Static variables (in function or file scope) and global variables are always initialized to zero.

Stack variables have no dependable value. To answer your question, uninitialized stack variables are often set to non-zero, so they often evaluate as true. That cannot be depended on.

When I was running Gentoo Linux I once found a bug in some open source Unicode handling code that checked an uninitialized variable against -1 in a while loop. On 32-bit x86 with GCC this code always ran fine, because the variable was never -1. On AMD-64 with its extra registers, the variable ended up always set to -1 and the processing loop never ran.

So, always use the compiler's high warning levels when building so you can find those bugs.

Zan Lynx