Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typecasting an array to pointer?

Tags:

arrays

c

pointers

Is is possible to typedef an array?

I have a set of vector function which all accept a pointer to a float which is an array of three floats. I can typedef float* vec3_t, however it will not let me create an object by simply setting it equal to an array in brackets.

typedef float* vec3_t;

vec3_t a = {1,1,1}; // Does not work
vec3_t b = (float[]){1,1,1}; // Works
float c[] = {1,1,1}; // Works

void f(vec3_t x);

f({1,1,1}); // Error
f((float[]){1,1,1}; // OK

Could someone please explain why this works this way?

like image 405
Stas Jaro Avatar asked Jun 10 '13 13:06

Stas Jaro


2 Answers

A pointer and an array are not the same thing. While they often behave in the same way, there are major differences, one of which you have just discovered.

What your code actually does

I have substituted the typedefed type with real type, to make the explaination clearer.

float c[] = {1,1,1};

You have simply created and initialized an array

f({1,1,1});

The code above is neither a lvalue nor rvalue. The {val1,...,valn} syntax is nothing more than an initializer and can not be used elsewehere.

float* b = (float[]){1,1,1};

In here you have created and initialized an array and then stored it's location in a pointer.

f((float[]){1,1,1};

This case is the same as the one above, but instead of storing the pointer you pass it as an argument to a function.

float* a = {1,1,1};

You are attempting to write three variables to a memory location that is not allocated yet. In general, {valn,...,valn}, is an initializer. At this moment you have nothing to initialize. Hence this syntax is invalid. You are trying to pour gas into a canister that has not yet been manufactured.

While I understand what you wanted to achieve, you seem to be missunderstanding the whole concept of memory and pointers. Imagine this code, which (in some dirty logic) is an equivalent of what you're trying to do:

float* a = NULL;
a[0] = 1;
a[1] = 1;
a[2] = 1;

What would happen if you executed this code?

So now you know why the compiler forbids it.

like image 94
Dariusz Avatar answered Sep 27 '22 17:09

Dariusz


You have to many different features piled into your code, so it is not exactly clear what you mean by "why this works this way". What's "this" specifically?

Anyway, in order to "typedef an array" you have to typedef an array, not pointer

typedef float vec3_t[3];

after which you will be able to do

vec3_t a = { 1, 1, 1 };

The rest of your code has nothing to do with typedefing an array. You simply discovered the compound literal syntax, which goes as (non-scalar-type) { initializers } and creates a nameless temporary object of the given type. The (non-scalar-type) part is an important part of compound literal syntax. You can't omit it.

So, instead of doing

vec3_t a = { 1, 1, 1 };
f(a);

if you don't care to have a named array object a, you can simply do

f((vec3_t) { 1, 1, 1 });

or

f((float [3]) { 1, 1, 1 });

or

f((float []) { 1, 1, 1 });

with the same effect.

like image 45
AnT Avatar answered Sep 27 '22 17:09

AnT