As Bart van Ingen Schoenau said, I believe that the standardization committee wanted to set as few restrictions as possible on the presentation of pointers. From the point of view of the compiler, it would be useful to have a clear view for int * and int const * , since constants can be placed in more or less memory, and therefore smaller pointers can be used to indicate smaller memories. This, however, meant that the %s format specifier for printf must have two versions: one for a constant line and one for a non-constant line. This would break a lot of legacy code, and I guess the standardization committee lacked the courage to enforce it in the community. And probably it is fair. Since there is no compelling reason to provide the same representation for int ** and int const ** , they left it that way. Using a different representation for this pointer, however, is unlikely to ever be useful, except perhaps for some applications with an angular register.
Perhaps they also decided that only the
char * and
char const * tags should have the same representation, just to save
%s , but maybe there are other interfaces that also require equality for pointers to other primitive types.
Similarly, for some systems, it is desirable to have a different representation of the pointer for something in the global memory, something on the stack and something on the heap. However, in C, you can use a pointer so that it can contain either such a pointer (again, you could think of varargs), and therefore you need to at least have a pointer representation that can represent all of them.
In the Embedded-C extension on memory space C, explicit permission has been introduced to the programmer to receive data from different data buses without the need for a pointer type that can represent them all. Such memory spaces can also be used to indicate allocated memory for constants, heaps, etc. Thus, a more efficient representation of pointers is provided.
One colleague of mine also mentioned that prototypes of K & R or, better, their absence, are still allowed. In such cases, the compiler cannot detect the difference in presentation between the declaration of the parameter and its use. This would undoubtedly lead to many undetected issues in outdated software. These problems can be solved by using a common view when passing parameters (including varargs), for example, for float to double in varags, but it will also compromise the supposed effectiveness of another view.