Suppose we have two structs
struct hello {
float a;
float b;
};
and
struct world {
float c;
float d;
};
and a function
void func(struct hello* h, struct world* w);
Is it the case that the two arguments can alias, as they both contain float
and therefore the compiler must generate a code that ensures correctness? If I am certain that w
and h
are not stored in the same memory location (or do not overlap in any way), would I achieve speed-up by changing the function to the following?
void func(struct hello *restrict h, struct world *restrict w);
Moreover, does the primitive type of float
have any effect on this or do the same rules apply to an int
?
Your example is very close to creating two structs that are of compatible type (C11 6.2.7). But in order to be compatible, they must have the same members with the same names, and the struct tags must also be the same.
You don't have that, so (TL;DR) the structs in the question cannot alias.
Another thing one can play around with however, is a trick called common initial sequence (C11 6.5.2.3) where you can put both structs inside a union, which is visible in the translation unit. You'd then be allowed to inspect the first sequence of members of each struct type, until the point where they stop being compatible. You could do this:
typedef union
{
struct hello h;
struct world w;
} hack_t;
Then access individual members of either struct. Unfortunately, this rule is a bit exotic and compilers don't always support it well apparently - the rule was subject to some Defect Reports (DR). I'm not certain of its status in current C17.
But regardless of that trick, the union still makes it possible to lvalue access a struct hello
or a struct world
through a hack_t
, since it is a union type that includes a compatible type among its members (C11 6.5/7). Mildly useful I suppose.
Apart from those cases, you cannot wildly cast pointer types from one pointer type to the other and de-reference. It would be a strict aliasing violation (C11 6.5/7) even if all individual members are compatible types. (You can however of course access any individual float
member by de-referencing a float
pointer to that member.)
Your restrict
optimization does not apply since the structs can't alias, unless they are truly compatible types. So the compiler will assume they are always in different memory regions.
It doesn't matter if you use float
or any other primitive data type, they all behave the same with the exception of the character types. A pointer to a character type can be used to access any data without strict aliasing violation (but not the other way around, reading character type through another incompatible type).