In the C standard is stated (emphasize mine):
Two types have compatible type if their types are the same. Additional rules for determining whether two types are compatible are described in 6.7.2 for type specifiers, in 6.7.3 for type qualifiers, and in 6.7.6 for declarators. 56)
56)Two types need not be identical to be compatible.
Source: C18, §6.2.7/1 - "Compatible type and composite type"
The information I get from these sentences is not much and not very helpful. The cited sections in general also provide no further information about what "compatible" exactly is/means.
I know now, that two types are compatible if they have the same type, but also can be compatible if they don't have the same type/be identical.
One place I found out where two non-identical types are compatible to each other is if I compare one type to a typedef
d type of this original type or to any typedef
d type of the original type, both types are compatible, as explained in the examples to §6.7.8/4 and /5:
§6.7.8/4:
EXAMPLE 1 After
typedef int MILES, KLICKSP(); typedef struct {doublehi, lo; } range;
the constructions
MILES distance; extern KLICKSP *metricp; range x; range z,*zp;
are all valid declarations. The type of
distance
isint
, that ofmetricp
is "pointer to function with no parameter specification returningint
", and that ofx
andz
is the specified structure;zp
is a pointer to such a structure. The objectdistance
has a type compatible with any otherint
object.
and
§6.7.8/5:
EXAMPLE 2 After the declarations
typedef structs1 { int x; } t1, *tp1; typedef structs2 { int x; } t2, *tp2;
type
t1
and the type pointed to bytp1
are compatible. Typet1
is also compatible with typestructs1
, but not compatible with the typesstructs2
,t2
, the type pointed to bytp2
, orint
.
but it only shows one example regarding the typedef
, where types can be compatible if not identical.
My questions:
Under which (all) circumstances can two types be compatible if they are not identical exactly? , and
What is a "compatible type" exactly? / What does it mean if two types are compatible to each other?
What specifies "compatibility"?
That is what I am looking for and couldn't found in the standard until yet.
If possible, please refer to sections from standard in the answers.
I discovered that compatibility is not mandatory related to range, representation or behavior:
§6.2.5/15:
The three types
char
,signed char
, andunsigned char
are collectively called the character types. The implementation shall definechar
to have the same range, representation, and behavior as eithersigned char
orunsigned char
.45)45)
CHAR_MIN
, defined in<limits.h>
, will have one of the values0
orSCHAR_MIN
, and this can be used to distinguish the two options. Irrespective of the choice made,char
is a separate type from the other two and is not compatible with either.
The cited sections 6.7.2, 6.7.3 and 6.7.6 do not explain more what a compatible type is, they only mandate rules for specific cases when a type shall be a compatible type.
§6.7.2/4:
Each enumerated type shall be compatible with char, a signed integer type, or an unsigned integer type. The choice of type is implementation-defined, 131) but shall be capable of representing the values of all the members of the enumeration. The enumerated type is incomplete until immediately after the } that terminates the list of enumerator declarations, and complete thereafter.
§6.7.3/11:
For two qualified types to be compatible, both shall have the identically qualified version of a compatible type; the order of type qualifiers within a list of specifiers or qualifiers does not affect the specified type.
§6.7.6.1/2:
For two pointer types to be compatible, both shall be identically qualified and both shall be pointers to compatible types.
§6.7.6.2/6:
For two array types to be compatible, both shall have compatible element types, and if both size specifiers are present, and are integer constant expressions, then both size specifiers shall have the same constant value. If the two array types are used in a context which requires them to be compatible, it is undefined behavior if the two size specifiers evaluate to unequal values.
§6.7.6.3/15:
For two function types to be compatible, both shall specify compatible return types.149) Moreover,the parameter type lists, if both are present, shall agree in the number of parameters and in use of the ellipsis terminator; corresponding parameters shall have compatible types. If one type has a parameter type list and the other type is specified by a function declarator that is not part of a function definition and that contains an empty identifier list, the parameter list shall not have an ellipsis terminator and the type of each parameter shall be compatible with the type that results from the application of the default argument promotions. If one type has a parameter type list and the other type is specified by a function definition that contains a (possibly empty) identifier list,both shall agree in the number of parameters, and the type of each prototype parameter shall be compatible with the type that results from the application of the default argument promotions to the type of the corresponding identifier. (In the determination of type compatibility and of a composite type, each parameter declared with function or array type is taken as having the adjusted type and each parameter declared with qualified type is taken as having the unqualified version of its declared type.)
149)If both function types are "old style", parameter types are not compared.
It actually comes from this:
- All declarations that refer to the same object or function shall have compatible type; otherwise, the behavior is undefined.
So from that you can see that anything that is allowed by the standard to work here, will be by necessity, compatible. For example the type int []
is distinct from int [10]
but they are compatible, because the standard allows you to declare
extern int foo[];
in one file and define
int foo[10];
in another file, and access foo
using the external identifier as an array of unknown size - therefore these types are compatible, but not identical.
It is stated explicitly in C11/18 6.7.6.2p6:
- For two array types to be compatible, both shall have compatible element types, and if both size specifiers are present, and are integer constant expressions, then both size specifiers shall have the same constant value. If the two array types are used in a context which requires them to be compatible, it is undefined behavior if the two size specifiers evaluate to unequal values.