tags:

views:

69

answers:

2

The code below is me trying to instantiate a 2d array, and it instantiating incorrectly: THE CODE:

    FILE* kernalFile = fopen(argv[1], "r");
    int rKernalSize;
    fscanf(kernalFile, "%d", &rKernalSize);
    unsigned int rKernal[rKernalSize][rKernalSize];

Data froma break point right after that code is ran: rKernalSize VALUES:

Name : rKernalSize
    Details:3
    Default:3
    Decimal:3
    Hex:0x3
    Binary:11
    Octal:03

rKernal VALUES:

Name : rKernal
    Details:0x7ffffffe0cd0
    Default:[0]
    Decimal:[0]
    Hex:[0]
    Binary:[0]
    Octal:[0]

or

rKernal[][0]

It should be rKernal[3][3] and here is the file so you can look at it. If wanted:

3 -1 1 0 1 0 -1 0 -1 1 3 -1 1 0 1 0 -1 0 -1 1 3 -1 1 0 1 0 -1 0 -1 1

TLDR: rKernalSize is correct (3) but when I create the 2d Array with rKernal[rKernalSize][rKernalSize] it does not instantiate correctly! It instatiates as rKernal[][0] maybe thats default but should be rKernal[3][3]

+1  A: 

The basic problem here is that rKernalSize isn't known at compile time when that array is being allocated. At compile time, the value of int rKernalSize is compiler-dependent (unless the new C standard explicitly makes it 0; 0's the value I'd bet on anyway.) So when the code is loaded, there's a symbol rKernal that represents the address of a secrtion of memory containing no bytes.

But then you run the program, and read '3' with your scanf; when you dumpt the results, you see '3'.

This code, by the way, wouldn't work in straight C -- you must allocate before the first executable statement. This will compile in C++.

Now, if you want, using straight C, to do something like this, here's what you need:

  • Read your size as you have using scanf.

  • Allocate the memory for your array using malloc, which will look something like

x

int ** ary;
int rkSize;  // what you scanf'd into
if((ary = malloc(rkSize*rkSize*sizeof(unsigned int)))==NULL){
     // for some reason your malloc failed.  You can't do much
     fprintf(stderr,"Oops!\n");
     exit(1);
 }
 // If you got here, then you have your array
  • Now, because of the pointer-array duality in C, you can treat this as your array x

    ary[1][1] = 42; // The answer

Charlie Martin
Exactly, you'll have to use "malloc" and allocate your memory dynamically. http://c-faq.com/aryptr/dynmuldimary.html
Michael Patterson
@Michael: Actually, no you don't. C99 introduced the concept of variable length arrays so this code is valid under that iteration of the standard. Buried in that linked page is the snippet `Finally, in C99 you can use a variable-length array.` :-)
paxdiablo
But how many compilers satisfy C99?
Charlie Martin
GCC does it just fine. The standards been around since, well, '99 I guess so, if your vendor doesn't support it `*cough*Microsoft*cough*`, you should think about moving :-) And the fact that the question wasn't about a _compile_ time error means that the questioner's compiler also supports C99.
paxdiablo
I don't believe you can index into `ary` as `ary[1][1]` as you've indicated; when you're allocating only one block of memory there's not enough information for the compiler to turn that into an appropriate offset. Indexing would instead need to be of the form `ary[1*rkSize + 1]`
Mark E
@paxdiablo: Correct you are. I've done almost all my C coding to the C90 standard I think. Anyway, thanks!
Michael Patterson
+2  A: 

Forget what the debugger is telling you. In your code, immediately following:

unsigned int rKernal[rKernalSize][rKernalSize];

put the statement:

printf ("%d\n", sizeof(rKernal) / sizeof(unsigned int));

and see what it prints out (hopefully 9).

It's possible the debugging information, created at compile time, is not enough to properly determine the sizes of variable length arrays.


By way of example, even though gcc supports variable length arrays, gdb itself couldn't properly handle them as recently as late 2009 and there's still no mention of them in the documentation dated October 2010.

So I suspect that is the problem, especially since the test code I provided above output 9 as expected.

paxdiablo
isn't `sizeof` evaluated at compile time? (ed: I guess for dynamically sized arrays in C99 it's [evaluated at run time](http://en.wikipedia.org/wiki/Sizeof)...)
Mark E
If I do that I get this warning: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘long unsigned int
Jacob Nelson
@Mark: No. C99 6.5.3.4/2 states `If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.`
paxdiablo
@Jacob: And when you run it, what happens?
paxdiablo
@paxdiablo: Prints out 9
Jacob Nelson
There you go then (ignore the warning, this line is a temporary one for debugging: you _could_ fix it with a proper format string but YAGNI). Bottom line: your array is being created correctly. The fact that your debugger does not have enough information to figure out how big it is at runtime is a deficiency of the debugger.
paxdiablo