In Modern C, Jens Gustedt states that:
With the exclusion of character types, only pointers of the same base type may alias.
But then I find this declaration of fgetpos()
in Annex B of the C standard:
int fgetpos(FILE * restrict stream, fpos_t * restrict pos);
where the fpos_t
type is defined as:
which is a complete object type other than an array type capable of recording all the information needed to specify uniquely every position within a file.
which begs the question:
Why can a fpos_t *
alias a FILE *
? Is it because fpos_t
can be a typedef
for FILE
? If not, what justifies the use of restrict
here?
First, the restrict
in a function declaration that is not a definition has no effect in C semantics. C 2018 6.7.6.3 15 says parameter qualifiers are ignored when determining function compatibility, and that means the function could be declared with restrict
on its parameters but defined without restrict
or vice-versa. So the use of restrict
in the documentation describing the routine is merely advice to the reader.
Normally, a FILE
and fpos_t
will not alias each other. (And note it is the object we are concerned about aliasing, not the pointer. The rules about aliasing in 6.5 7 are about what lvalue types may be used to access an object, not about pointers may be used [except of course when considering actually aliasing a pointer].) However, you could (in the sense it is possible, not advisable) have declared a union that contains both a FILE
(if your C implementation defines it as a complete type) and a fpos_t
, so you are passing in a properly prepared FILE
object and are willing to have it sacrificed and replaced by an fpos_t
in the same memory. You could also be doing this with dynamically allocated memory, since writing a new type (fpos_t
) over an old type (FILE
) is an allowed form of aliasing (when writing to dynamically allocated memory, whatever type you are using is the effective type, which is allowed for aliasing). So the restrict
in the documentation for fgetpos
is advising you not to do that.