Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typedef an unconstrained float array in C

Tags:

arrays

c

typedef

I made a typedef for float arrays, like this:

typedef float fooType[];

So that I can declare and initialise float arrays statically like this:

fooType myArray = {1.0, 2.0, 3.0}

That works fine. I can say myArray[2] with no problems and generally use my fooType as I'd like. In the context of my program it's very clear that fooType is an array type (it's actually a giant lookup table) which is why I'm not simply doing typedef float fooType.

How do I then declare and use a variable to point to bar and access the elements of bar? I cannot declare a simple variable like this:

fooType bar = myArray;

Since that errors with invalid initializer; I didn't expect it to work since the compiler doesn't know how much memory to allocate. I tried a few things with pointers:

fooType *bar = myArray; 

This gives a warning: initialization from incompatible pointer type and errors when I access the elements with bar[1].. This declares fine, as I'd expect it to since the types match now:

fooType *bar = &myArray;

But as above the compiler errors with an invalid use of array with unspecified bounds when I say bar[1].

This works:

float *bar = myArray; 
float val = bar[3]; 

But I don't want to because I lose the readability of my typedef.

I've been buried for a long time in a cuddly OO world (Java), so I hope to understand from this what's idiomatic in C in this situation. I'm quite prepared to change my use of the typedef to suit convention if there is no direct solution. I have a feeling there is though, and it's not complicated.

Thanks

like image 743
Tim Avatar asked Nov 29 '11 00:11

Tim


1 Answers

The problem you're encountering here is the fact that arrays are not pointers in C, but rather decay to pointers to the first element when used on the right-hand side of the assignment operator. Thus, if you declare an array like

fooType myArray = {1.0, 2.0, 3.0}

the type of myArray is float[3], and &myArray is (*float)[3], or "pointer to an array of 3 floats". Thus you can't simply say

fooType *bar = myArray;

The type fooType* is not a pointer to a float ... thus it's an incompatible pointer type. Doing

fooType* bar = &myArray;

does work, but the problem you're encountering is that bar[1] is not an element in the array myArray, since bar itself is a pointer. You would have to dereference bar like (*bar)[1] to access an element in myArray. For instance:

typedef float fooType[];
fooType myArray = {1.0, 2.0, 3.0}
fooType* bar = &myArray;
(*bar)[1] = 5.0;

Finally, keep in mind that with C, you cannot assign one array to another array ... so you can'd do something like:

fooType bar = myArray;

This goes back to the whole issue of arrays and their decay into pointers to the first element, and the fact that the type of the array itself is not the same as the type of the first element in the array.

You may in the end simply want to typedef the array, and then typedef the array element types since of using float so that anyone using your code will know what one type of element belongs with the other.

like image 176
Jason Avatar answered Oct 24 '22 11:10

Jason