Sign in to follow this  

Wanna see something wierd?

This topic is 4751 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Okay, dig this. A friend of mine asked me to show him an example of how to use dynamic array initialization in C (using user input values or variables provided by functions to init arrays, instead of hard-coding the values). So I whipped this up right quick:
#include <stdio.h>

#define ARRAY_SIZE 5

int main(void)
{
	int array1size = 4;
	int array2size = 5;
	int lastnum = 1;
	int c = 0;
	int d = 0;
	char choice = 0x00;

	printf("Enter I to input the values manually, or D to use the pre-defined values: \n");
	scanf("%c", &choice);

	if ( choice == 'I') {

		printf("Enter array 1 and 2 sizes (separated by a space):\n ");
		scanf("%d", &array1size);
		scanf("%d", &array2size);

	}
	else if ( choice == 'D' ) {
		array1size = ARRAY_SIZE*1;
		array2size = ARRAY_SIZE*2;
	}

	int array[array1size][array2size];

	// oddly enough, if you were to input negative
	// values and change these for loops to count backwards
	// from 0 instead of forward, it would still work just
	// fine.

        for ( c = 0; c < array1size; c++ )
        {
                for ( d = 0 ; d < array2size ; d++ )
                {
                        array[c][d] = lastnum*lastnum;
                        lastnum++;
                        printf("\narray[%d][%d] now contains: %d\n",
                                c, d, array[c][d]);
                }
        }

	return 0;
}


Like the comment says, I found out something interesting - if you pass negative values, and change the less-thans to greater-thans, and have the loop count backwards, you'll still get a perfectly functioning array. ?? Is this a bug in GCC 3.3.4, or was C meant to do this? Or was this just something nobody ever considered, and therefore didn't see any reason to stop it? ANOTHER interesting tidbit: if you were to pass an array initialiser an empty variable (say an int you had declared but not yet initialised), the array would still be created - and, in fact, you could assign any arbitrary value TO that array. Say, for example, we built array D with undefined index I (int d[i]). We could then assign anything to d[x], as long as X was defined, on to infinity (theoretically, bound only by the size of accessible memory). But the MINUTE we try to pass an undefined variable as x (like we did with i), we get a segmentation fault. Using an uninitialised int, I was able to build an array and fill it with 84095 values of int size. To wit:
#include <stdio.h>
int main(void)
{
        long i;

        int d[i];

        // to prove we can pass an arbitrary constant and
        // not crash things (again, assuming &d + constant*sizeof(array type)
        // is within addressable memory, which it most likely will not
        // always be)

        d[32767] = 5;
        printf("%d\n", d[32767]);

        // if you take this line out and leave i uninitialized,
        // the program will throw a segmentation fault and happily
        // crash you back to the console.                
        i = 0;

        while ( 1 )
        {
                d[i] = i;
                printf("%d\n", d[i]);
                i++;
        }
        return 0;
}


... Now, I made it clear to him that the first source example was the proper way to do it. But I'm puzzled as to why the second to ways work at all. Has anyone used the functionality of either one of these instances, or have any idea why it is there? Should I report either one of these things to the good folks at GNU as a bug?

Share this post


Link to post
Share on other sites
For the first one, what's happening is GCC considers the array like this:

|--------------|-------------------|
Accessed: | 1 | 2 | 3 | 0 | 1 | 2 | 3 |
|--------------|-------------------|

|--------------|-------------------|
Indexed: | -3 | -2 | -1 | 0 | 1 | 2 | 3 |
|--------------|-------------------|


When you pass a negative index it loops around to the end of the array. I don't know if this is standard behaviour though.

The second example though is behaving exactly as expected. The reason you get a segmentation fault when you don't comment out i=0 is that you're trying to access the element 1 past the end of whatever the array was initialized as. It's liking access d[4] of an array with 4 elements. By setting it to zero you start at the beginning of the array, if you let it run for long enough it would eventually reach the end of the array and seg fault, but since you're printing the the screen that'll probably take a while (depending on the undefined value of i).

Share this post


Link to post
Share on other sites
Yeah I know, the segmentation fault isn't what I'm confused about.

What I'm confused about is why it's letting me construct an array of
i
size when
i
is clearly undefined. Shouldn't this result in a compile time error, or at least a runtime error? I mean we were all taught to think that uninitialized variables didn't even contain 0...

Share this post


Link to post
Share on other sites
i isn't undefined, we know exactly what i is, it's a long. However, the value of i is undefined. This doesn't mean that i doesn't have a value, it just means we have no way of knowing what that value is until the program is run. It could be 0, it could be 1000, it could be 2398764598, you just don't know. However, you can still use the value of i because at runtime i gets whatever happened to be in memory where it was allocated (allocation and initialisation are 2 different things).

Share this post


Link to post
Share on other sites
Quote:
Original post by andrewk3652
Okay, dig this. A friend of mine asked me to show him an example of how to use dynamic array initialization in C (using user input values or variables provided by functions to init arrays, instead of hard-coding the values). So I whipped this up right quick:


IIRC, that ain't C. It's a bastardisation of C++. C doesn't support dynamic arrays. At least, C89 doesn't. C99 might, though. With C89 you'd have to malloc it.

Share this post


Link to post
Share on other sites
Quote:
Original post by andrewk3652
Okay, dig this. A friend of mine asked me to show him an example of how to use dynamic array initialization in C (using user input values or variables provided by functions to init arrays, instead of hard-coding the values). So I whipped this up right quick:

*** Source Snippet Removed ***

Like the comment says, I found out something interesting - if you pass negative values, and change the less-thans to greater-thans, and have the loop count backwards, you'll still get a perfectly functioning array. ?? Is this a bug in GCC 3.3.4, or was C meant to do this? Or was this just something nobody ever considered, and therefore didn't see any reason to stop it?

ANOTHER interesting tidbit: if you were to pass an array initialiser an empty variable (say an int you had declared but not yet initialised), the array would still be created - and, in fact, you could assign any arbitrary value TO that array. Say, for example, we built array D with undefined index I (int d[i]). We could then assign anything to d[x], as long as X was defined, on to infinity (theoretically, bound only by the size of accessible memory). But the MINUTE we try to pass an undefined variable as x (like we did with i), we get a segmentation fault. Using an uninitialised int, I was able to build an array and fill it with 84095 values of int size. To wit:

*** Source Snippet Removed ***

... Now, I made it clear to him that the first source example was the proper way to do it. But I'm puzzled as to why the second to ways work at all.

Has anyone used the functionality of either one of these instances, or have any idea why it is there? Should I report either one of these things to the good folks at GNU as a bug?
"Propper way to do it" - WTF?!?!?! What the hell are you on about!!!

That isn't any kind of way to do dynamic arrays at all - It should never compile! You cannot declare an array with non-constant size ever, AFAIK! Is this some kind of a joke, or does that version of gcc allow non-constant values for an array size? Surely it can't possibly actually work?! It certainly doesn't work on any other compiler!

You should learn how to actually allocate and deallocate memory using malloc and free.

Share this post


Link to post
Share on other sites
Quote:
Original post by iMalc
Quote:
Original post by andrewk3652
Okay, dig this. A friend of mine asked me to show him an example of how to use dynamic array initialization in C (using user input values or variables provided by functions to init arrays, instead of hard-coding the values). So I whipped this up right quick:

*** Source Snippet Removed ***

Like the comment says, I found out something interesting - if you pass negative values, and change the less-thans to greater-thans, and have the loop count backwards, you'll still get a perfectly functioning array. ?? Is this a bug in GCC 3.3.4, or was C meant to do this? Or was this just something nobody ever considered, and therefore didn't see any reason to stop it?

ANOTHER interesting tidbit: if you were to pass an array initialiser an empty variable (say an int you had declared but not yet initialised), the array would still be created - and, in fact, you could assign any arbitrary value TO that array. Say, for example, we built array D with undefined index I (int d[i]). We could then assign anything to d[x], as long as X was defined, on to infinity (theoretically, bound only by the size of accessible memory). But the MINUTE we try to pass an undefined variable as x (like we did with i), we get a segmentation fault. Using an uninitialised int, I was able to build an array and fill it with 84095 values of int size. To wit:

*** Source Snippet Removed ***

... Now, I made it clear to him that the first source example was the proper way to do it. But I'm puzzled as to why the second to ways work at all.

Has anyone used the functionality of either one of these instances, or have any idea why it is there? Should I report either one of these things to the good folks at GNU as a bug?
"Propper way to do it" - WTF?!?!?! What the hell are you on about!!!

That isn't any kind of way to do dynamic arrays at all - It should never compile! You cannot declare an array with non-constant size ever, AFAIK! Is this some kind of a joke, or does that version of gcc allow non-constant values for an array size? Surely it can't possibly actually work?! It certainly doesn't work on any other compiler!

You should learn how to actually allocate and deallocate memory using malloc and free.
im with iMalc on this one, W_T_F.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
http://www.redhat.com/docs/manuals/enterprise/RHEL-3-Manual/gcc/variable-length.html

Basically its a ISO C99 extension. Not all compilers support it, and GCC erronously supports it as a part of C89 and c++ modes (GCC is not C99 compilent yet).

I HIGHLY suggest learning to use malloc and free, since that is more supported and helps get you used to memory mangment issues. Besides you cant free those varibles and reallocate them to a new size while the app is running. Pretty much they are useful only as temp varibles. Not useful in game coding for loading maps (unless you exit the game on map changes).

Share this post


Link to post
Share on other sites
That's what I thought so I tried it myself. GCC 3.2 compiles it quite happily.

EDIT: The following code shows that the array is indeed dynamically allocated on the stack:


#include <time.h>
#include <stdio.h>
#include <stdlib.h>


int main(void)
{
srand(time(0));
long i = rand()%10;

int d[i];
int *e = new int[i];

printf("Addr of i: 0x%x\n",&i);
printf("Addr of d: 0x%x\n",&d);
printf("Addr of e: 0x%x\n",e);
for(int j=0 ; j<i ; ++j) d[j] = j;
for(int j=0 ; j<i ; ++j) printf("%d\n", d[j]);

delete[] e;
return 0;
}

Share this post


Link to post
Share on other sites
The GCC team is a bit idiosyncratic when it comes to compiler extensions it would seem. As for the size issue, perhaps it is being silently converted into a unsigned integer?

Share this post


Link to post
Share on other sites
Our teacher told us that
	else if ( choice == 'D' ) {

is invalid in C, you will have to do:
	else 
if ( choice == 'D' ) {

Well, at least in exams.
I don't know what's the different, maybe in the first C's it was invalid

Share this post


Link to post
Share on other sites
Quote:
Original post by pex22
Our teacher told us that
	else if ( choice == 'D' ) {

is invalid in C, you will have to do:
	else 
if ( choice == 'D' ) {

Well, at least in exams.
I don't know what's the different, maybe in the first C's it was invalid


WTH? why? it sounds fishy. oh, well, i don't use c, so i can happily get on with else and its if on the same line (i'd actually define an elseif macro, but that's a bit much =)

Share this post


Link to post
Share on other sites
@pex22
Both ways are perfectly legal. In fact, it doesn't matter what kind of whitespaces you use, it's all the same to the compiler.

[Edited by - Luctus on December 14, 2004 7:29:40 AM]

Share this post


Link to post
Share on other sites
From gcc info-pages: "Variable-length automatic arrays are allowed in ISO C99, and as an extension GCC accepts them in C89 mode and in C++. (However, GCC's implementation of variable-length arrays does not yet conform in detail to the ISO C99 standard.)"

These GNU extensions print warnings if -pedantic flag is used.. and if you really don't wan't to use those extension (by mistake) use -Werror flag in addition so your code does not even compile.

Share this post


Link to post
Share on other sites
Quote:
Original post by pex22
Our teacher told us that
	else if ( choice == 'D' ) {

is invalid in C, you will have to do:
	else 
if ( choice == 'D' ) {

Well, at least in exams.
I don't know what's the different, maybe in the first C's it was invalid

Bull. Any undergrad compiler would be able to regard the two as the same.

Share this post


Link to post
Share on other sites
As to the OP - I'm gonna have to third the 'doubleyew tee EFF?!' sentiment.

As for pex22's teacher - I'm guessing this is the same kind of academic ivory-tower bullcrap we got in uni. We actually lost marks for things such as putting in redundant brackets, despite the fact that such things are often aids to comprehension in the Real World(TM). In fact, the compiler I'm using at work at the moment won't allow you to use an operator sequence that's ambiguous to read, even though it as an unambiguous meaning in terms of C++'s left- and right-binding rules.

Share this post


Link to post
Share on other sites
Quote:
Original post by joanusdmentia
That's what I thought so I tried it myself. GCC 3.2 compiles it quite happily.

EDIT: The following code shows that the array is indeed dynamically allocated on the stack:

*** Source Snippet Removed ***
Oh far out, so it's like alloca then? I was thinking that it wouldn't work for globals anyway. Then there's structs containing the variable-size arrays, it can't merely be a pointer or you couldn't assign one struct to another to copy them etc. I can't imagine how they plan on fitting it into the language particularly nicely or consistently.

At this stage, with a not-fully supporting compiler, unportability, probably next to zero documentation or books on this method, the disadvantages compared to malloc etc, I suggest avoiding it, at least, for now.

Share this post


Link to post
Share on other sites
For everyone's benefit, the reason I provided this type of example instead of an malloc/free example was because the friend specifically asked me if it could be done this way.

Yes, malloc/free are the preferred way of doing things, but this is still perfectly valid.

Share this post


Link to post
Share on other sites
Quote:
Original post by iMalc
Oh far out, so it's like alloca then? I was thinking that it wouldn't work for globals anyway. Then there's structs containing the variable-size arrays, it can't merely be a pointer or you couldn't assign one struct to another to copy them etc.

Yep, although with alloca the stack space is only unallocated when the function returns whereas variable-sized arrays have the potential to be unallocated when they go out of scope, I'm not sure if they are though. Also, variable-sized arrays can only be used inside a function, otherwise the compiler hisses and spits at you....well, you'll get an error at least.

Quote:
Original post by andrewk3652
Yes, malloc/free are the preferred way of doing things, but this is still perfectly valid.

Something working and something being perfectly valid are 2 different things [smile]

Share this post


Link to post
Share on other sites

This topic is 4751 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this