Wanna see something wierd?

Started by
19 comments, last by joanusdmentia 19 years, 4 months ago
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). 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;

        // 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;
                printf("%d\n", d);
                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?
=========================Buildium. Codium. Fragium.http://www.aklabs.net/=========================
Advertisement
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).
"Voilà! In view, a humble vaudevillian veteran, cast vicariously as both victim and villain by the vicissitudes of Fate. This visage, no mere veneer of vanity, is a vestige of the vox populi, now vacant, vanished. However, this valorous visitation of a bygone vexation stands vivified, and has vowed to vanquish these venal and virulent vermin vanguarding vice and vouchsafing the violently vicious and voracious violation of volition. The only verdict is vengeance; a vendetta held as a votive, not in vain, for the value and veracity of such shall one day vindicate the vigilant and the virtuous. Verily, this vichyssoise of verbiage veers most verbose, so let me simply add that it's my very good honor to meet you and you may call me V.".....V
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...
=========================Buildium. Codium. Fragium.http://www.aklabs.net/=========================
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).
"Voilà! In view, a humble vaudevillian veteran, cast vicariously as both victim and villain by the vicissitudes of Fate. This visage, no mere veneer of vanity, is a vestige of the vox populi, now vacant, vanished. However, this valorous visitation of a bygone vexation stands vivified, and has vowed to vanquish these venal and virulent vermin vanguarding vice and vouchsafing the violently vicious and voracious violation of volition. The only verdict is vengeance; a vendetta held as a votive, not in vain, for the value and veracity of such shall one day vindicate the vigilant and the virtuous. Verily, this vichyssoise of verbiage veers most verbose, so let me simply add that it's my very good honor to meet you and you may call me V.".....V
I guess so.

I guess the point remains that, like I said in the first example, know what the hell you're passing around. :-)
=========================Buildium. Codium. Fragium.http://www.aklabs.net/=========================
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.
My stuff.Shameless promotion: FreePop: The GPL god-sim.
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). 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.
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms
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). 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.
"I am a donut! Ask not how many tris/batch, but rather how many batches/frame!" -- Matthias Wloka & Richard Huddy, (GDC, DirectX 9 Performance)

http://www.silvermace.com/ -- My personal website
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).
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;    int *e = new int;    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;}
"Voilà! In view, a humble vaudevillian veteran, cast vicariously as both victim and villain by the vicissitudes of Fate. This visage, no mere veneer of vanity, is a vestige of the vox populi, now vacant, vanished. However, this valorous visitation of a bygone vexation stands vivified, and has vowed to vanquish these venal and virulent vermin vanguarding vice and vouchsafing the violently vicious and voracious violation of volition. The only verdict is vengeance; a vendetta held as a votive, not in vain, for the value and veracity of such shall one day vindicate the vigilant and the virtuous. Verily, this vichyssoise of verbiage veers most verbose, so let me simply add that it's my very good honor to meet you and you may call me V.".....V

This topic is closed to new replies.

Advertisement