The concept of compatible types combines the notions of being able to use
two types together without modification (as in an assignment expression),
being able to substitute one for the other without modification, and uniting
them into a composite type. A composite type is that which
results from combining two compatible types. Determining the resultant
composite type for two compatible types is similar to following the usual
binary conversions of integral types when they are combined with some
arithmetic operators.
Obviously, two types that are the same are compatible; their composite type is the same type. Less obvious are the rules governing type compatibility of non-identical types, function prototypes, and type-qualified types. Names in typedef definitions are only synonyms for types, and so typedef names can possibly indicate identical and therefore compatible types. Pointers, functions, and arrays with certain properties can also be compatible types.
Identical Types
The presence of type specifiers in various combinations for arithmetic types may or may not indicate different types. For example, the type signed int is the same as int, except when used as the types of bit fields; but char, signed char, and unsigned char are different types.
The presence of a type qualifier changes the type. That is, const int is not the same type as int, and therefore the two types are not compatible.
Two arithmetic types are compatible only if they are the same type.
Compatibility Across Separately Compiled Source Files
The definition of a structure, union, or enumeration results in a new type. When the definitions for two structures, unions, or enumerations are defined in separate source files, each file can theoretically contain a different definition for an object of that type with the same name. The two declarations must be compatible, or the run time behavior of the program is undefined. Therefore, the compatibility rules are more restrictive and specific than those for compatibility within the same source file. For structure, union, and enumeration types defined in separately compiled files, the composite type is the type in the current source file.
The requirements for compatibility between two structure, union, or enumerated types declared in separate source files are as follows:
For enumerations, corresponding members must also have the same values.
For structures and unions, the following additional requirements must be met for type compatibility:
See Related References for links to specific compatibility rules.
A separate notion of type compatibility as distinct from being of the same
type does not exist in C++. Generally speaking, type checking in C++ is
stricter than in C: identical types are required in situations where C
would only require compatible types.
Related References