Danijel
Danijel

Reputation: 8610

Casting C float array to struct of floats and vice-versa?

typedef struct cmplx {
    float re;
    float im;
} cmplx_t;

Can float array be safely cast to this complex type?

Like so:


float s[SIZE*2];

cmplx_t* c = (cmplx_t*) s; // ?? 

What about the vice-versa, struct to float pointer?


cmplx_t c[SIZE];

float* c = (float*) c; // ?? 

Upvotes: 3

Views: 436

Answers (1)

Eric Postpischil
Eric Postpischil

Reputation: 223633

Original Question

Can an array of float be accessed through a cmplx_t *?

The language in the C standard appears to permit this. First, we have to consider the conversion of s, which is automatically converted to a pointer, to cmplx_t *. C 2018 6.3.2.3 7 partially defines the conversion as long as the alignment is correct. The standard does not guarantee that the alignment requirement of a structure is at most the strictest alignment requirement of its members, but this is typical, so the conversion is defined in ordinary C implementations.

Then we have to consider the aliasing rule. C 2018 6.5 7 says:

An object shall have its stored value accessed only by an lvalue expression that has one of the following types:

— a type compatible with the effective type of the object,

— a qualified version of a type compatible with the effective type of the object,

— a type that is the signed or unsigned type corresponding to the effective type of the object,

— a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,

— an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or

— a character type.

Since c points to memory that was defined as float objects, float is “a type compatible with the effective type of the object”, and *c is “an aggregate or union type that includes one of the aforementioned types among its members.” Therefore, *c, c->re, and c->im ought to be accesses permitted by the aliasing rule.

The C standard also does not specify that the layout of cmplx_t has the im member immediately following the re member. C implementations are allowed to insert padding between members and at the end of the structure. However, with members of the same type, there is no reason to do so, and typical C implementations do not. So, in ordinary C implementations, c->re and c->im should access the desired elements of the float array, and so should c[i].re and c[i].im.

Added Question

Can an array of cmplx_t be accessed through a float *.

The C standard does not define the behavior of attempting this. For an object of type cmplx_t, float is not any of the types listed above.

Upvotes: 6

Related Questions