Welcome to Software Development on Codidact!
Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.
Post History
Assuming that there are no alignment problems between the two pointer types (impl-defined), the code is otherwise well-defined. As per the quoted 6.3.2.3 C allows pretty much any form of wild and c...
Answer
#1: Initial revision
Assuming that there are no alignment problems between the two pointer types (impl-defined), the code is otherwise well-defined. As per the quoted 6.3.2.3 C allows pretty much any form of wild and crazy pointer conversions by means of a cast, as long as you don't actually de-reference the pointer through the wrong type. As for the original intention of strict pointer aliasing, it was exactly for cases like this where the compiler should be allowed to assume that `double *f` and `int64_t *j` do not alias, especially when the caller is in a different translation unit. But since you overrule all such internal decisions with the explicit cast, the compiler just has to fall in line. And it is fine to convert back to the correct pointer type. `restrict` is only an optimizer hint to the compiler and in this case of using the same variable for both arguments, the caller would be violating the "restrict contract" between the caller and a `restrict` qualified function. I don't know of any compiler which actually checks for `restrict` violations by the caller. If you would remove the cast and assignment in the function, then the compiler would still be free to assume that the pointers don't alias even without `restrict`. I managed to create a peculiar example with gcc and clang -O3 ```c #include <inttypes.h> #include <stdio.h> void bar(double *f, int64_t * j) { int64_t tmp = *j; *f = 1.0; if(*j == tmp) printf("%"PRIi64 " %"PRIi64 "\n", *j, tmp); } int main (void) { int64_t i = 1; bar((double *) &i, &i); printf("%" PRIi64 "\n", i); } ``` Output: ```text 1 1 4607182418800017408 ``` Apparently the compiler assumes: - `tmp` holds the value of `*j` - Thus `tmp` and `*j` have the same value, since `*j` has not been changed. - Thus print `tmp` twice (why load `*j` from RAM again?). - Then on the caller side print the actual value of `*j` which may have changed by the function with external linkage. Without -O3 the `1 1` is never printed. The same thing happens at -O3 if I change the function to: ```c void bar(int64_t*restrict f, int64_t*restrict j) { int64_t tmp = *j; *f = 2; if(*j == tmp) printf("%"PRIi64 " %"PRIi64 "\n", *j, tmp); } ``` However, if `restrict` is dropped it does not print `1 1` regardless of optimizations.