Dismiss
Announcing Stack Overflow Documentation

We started with Q&A. Technical documentation is next, and we need your help.

Whether you're a beginner or an experienced developer, you can contribute.

Sign up and start helping → Learn more about Documentation →

In C99, is there a big different between these two?:

int main() {
    int n , m;
    scanf("%d %d", &n, &m);
    int X[n][m];

    X[n-1][m-1] = 5;
    printf("%d", X[n-1][m-1]);
}

and:

int main(int argc, char *argv[]) {
    int n , m;
    int X[n][m];
    scanf("%d %d", &n, &m);

    X[n-1][m-1] = 5;
    printf("%d", X[n-1][m-1]);
}

The first one seems to always work, whereas the second one appears to work for most inputs, but gives a segfault for the inputs 5 5 and 6 6 and returns a different value than 5 for the input 9 9. So do you need to make sure to get the values before declaring them with variable length arrays or is there something else going on here?

share|improve this question
4  
The second is plain wrong... since n and m aren't initialised. The int X[n][m]; uses the values m and n have at that point in the code -- you can't just set them later, nor can you resize the array by changing them later. – Dmitri Jul 7 at 2:09
    
Ok thanks, wanted to make sure it was just an ordering thing and not something else I hadn't thought of. – Jake Jul 7 at 2:10
up vote 5 down vote accepted

When the second one works, it's pure chance. The fact that it ever works proves that, thankfully, compilers can't yet make demons fly out of your nose.

Just declaring a variable doesn't necessarily initialize it. int n, m; leaves both n and m with undefined values (in this case, at least), and attempting to access those values is undefined behavior. If the values in the bits of memory those point to happen to be larger than the values entered for n and m -- which is very, very far from guaranteed -- then your code will work; if not, it won't. Your compiler could also have made this segfault, or made it melt your CPU; it's undefined behavior, so anything can happen.

For example, let's say that the area of memory dedicated to n happened to contain the number 87, and m got 14. If you then entered an n of 12 and an m of 6, you're golden -- the array happens to be big enough. On the other hand, if n got 4 and m got 2, then your code will look past the end of the array, and you'll get undefined behavior. Of course, this is all fluff and speculation depending on the compiler, OS, time of day, and phase of the moon,1 and you can't rely on any numbers happening to be initialized to the right ones.

With the first one, on the other hand, you're assigning the values through scanf, so (assuming it doesn't error) (and the entered numbers aren't negative) (or zero) you're guaranteed to have valid indices, because the array is guaranteed to be big enough because the variables are initialized properly.


Just to be clear, even though variables are reliably zero-initialized under some circumstances doesn't mean you should rely on that behavior. You should always explicitly give variables a default value, or initialize them as soon as possible after their declaration.


1: Source: Ryan Bemrose, in chat

share|improve this answer

int X[n][m]; means to declare an array whose dimensions are the values that n and m currently have. C code doesn't look into the future; statements and declarations are executed in the order they are encountered.

In your second code you did not give n or m values, so this is undefined behaviour which means that anything may happen.

Here is another example of sequential execution:

int x = 5;
printf("%d\n", x);
x = 7;

This will print 5, not 7.

share|improve this answer
2  
This post feels... more than a little sarcastic and condescending, tbh. Maybe it's that it's such a basic thing that seems obvious to me, so seeing any explanation of it sounds condescending. – QPaysTaxes Jul 7 at 2:31
3  
@QPaysTaxes I'm just trying to speak plainly , no sarcasm or condescension is intended – M.M Jul 7 at 2:39
    
Fair enough. It's probably all in my head. – QPaysTaxes Jul 7 at 2:44

The second one should produce bugs because n and m are initialized with pretty much random values if they're local variables. If they're global, they'll be with value 0.

share|improve this answer
    
"any version of C++" - VLAs are a C thing. C++ does not have them. – user2357112 Jul 7 at 2:13
    
Oh yeah. You can use C++ and still allow them, so I forgot about that. – Andros Rex Jul 7 at 2:29

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.