A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://en.cppreference.com/w/cpp/language/../../c/language/compatible_type.html below:

Type - cppreference.com

(See also arithmetic types for the details on most built-in types and the list of type-related utilities that are provided by the C library.)

Objects, functions, and expressions have a property called type, which determines the interpretation of the binary value stored in an object or evaluated by the expression.

[edit] Type classification

The C type system consists of the following types:

  • standard: signed char, short, int, long, long long(since C99)
  • bit-precise: _BitInt(N) where N is an integer constant expression that specifies the number of bits that are used to represent the type, including the sign bit. Each value of N designates a distinct type.
(since C23)
  • extended: implementation defined, e.g. __int128
(since C99)
  • standard: _Bool,(since C99) unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long(since C99)
  • bit-precise: unsigned _BitInt(N) where N is an integer constant expression that specifies the number of bits that are used to represent the type. Each value of N designates a distinct type. This category includes the type unsigned _BitInt(1) which does not have a corresponding bit-precise signed integer type.
(since C23)
  • extended: implementation-defined, e.g. __uint128
(since C99)
  • real floating-point types: float, double, long double
  • decimal real floating-point types: _Decimal32, _Decimal64, _Decimal128
(since C23)
  • complex types: float _Complex, double _Complex, long double _Complex
  • imaginary types: float _Imaginary, double _Imaginary, long double _Imaginary
(since C99)

For every type listed above several qualified versions of its type may exist, corresponding to the combinations of one, two, or all three of the const, volatile, and restrict qualifiers (where allowed by the qualifier's semantics).

[edit] Type groups

Constructing a complete object type such that the number of bytes in its object representation is not representable in the type size_t (i.e. the result type of sizeof operator), including forming such a VLA type at runtime,(since C99) is undefined behavior.

[edit] Compatible types

In a C program, the declarations referring to the same object or function in different translation units do not have to use the same type. They only have to use sufficiently similar types, formally known as compatible types. Same applies to function calls and lvalue accesses; argument types must be compatible with parameter types and lvalue expression type must be compatible with the object type that is accessed.

The types T and U are compatible, if

  • Corresponding members must be declared in the same order (structures only)
  • Corresponding bit-fields must have the same widths.
(until C23)

The type char is not compatible with signed char and not compatible with unsigned char.

If two declarations refer to the same object or function and do not use compatible types, the behavior of the program is undefined.

// Translation Unit 1
struct S { int a; };
extern struct S *x; // compatible with TU2's x, but not with TU3's x
 
// Translation Unit 2
struct S;
extern struct S *x; // compatible with both x's
 
// Translation Unit 3
struct S { float a; };
extern struct S *x; // compatible with TU2's x, but not with TU1's x
 
// the behavior is undefined
// Translation Unit 1
#include <stdio.h>
 
struct s { int i; }; // compatible with TU3's s, but not TU2's
extern struct s x = {0}; // compatible with TU3's x
extern void f(void); // compatible with TU2's f
 
int main()
{
    f();
    return x.i;
}
 
// Translation Unit 2
struct s { float f; }; // compatible with TU4's s, but not TU1's s
extern struct s y = {3.14}; // compatible with TU4's y
void f() // compatible with TU1's f
{
    return;
}
 
// Translation Unit 3
struct s { int i; }; // compatible with TU1's s, but not TU2's s
extern struct s x; // compatible with TU1's x
 
// Translation Unit 4
struct s { float f; }; // compatible with TU2's s, but not TU1's s
extern struct s y; // compatible with TU2's y
 
// the behavior is well-defined: only multiple declarations
// of objects and functions must have compatible types, not the types themselves

Note: C++ has no concept of compatible types. A C program that declares two types that are compatible but not identical in different translation units is not a valid C++ program.

[edit] Composite types

A composite type can be constructed from two types that are compatible; it is a type that is compatible with both of the two types and satisfies the following conditions:

(since C99)
The element type of the composite type is the composite type of the two element types.
(until C23)

These rules apply recursively to the types from which the two types are derived.

// Given the following two file scope declarations:
int f(int (*)(), double (*)[3]);
int f(int (*)(char *), double (*)[]); // C23: Error: conflicting types for 'f'
// The resulting composite type for the function is:
int f(int (*)(char *), double (*)[3]);

For an identifier with internal or external linkage declared in a scope in which a prior declaration of that identifier is visible, if the prior declaration specifies internal or external linkage, the type of the identifier at the later declaration becomes the composite type.

[edit] Incomplete types

An incomplete type is an object type that lacks sufficient information to determine the size of the objects of that type. An incomplete type may be completed at some point in the translation unit.

The following types are incomplete:

extern char a[]; // the type of a is incomplete (this typically appears in a header)
char a[10];      // the type of a is now complete (this typically appears in a source file)
struct node
{
    struct node* next; // struct node is incomplete at this point
}; // struct node is complete at this point
[edit] Type names

A type may have to be named in context other than the declaration. In these situations, type name is used, which is, grammatically, exactly the same as a list of type-specifiers and type-qualifiers, followed by the declarator (see declarations) as would be used to declare a single object or function of this type, except that the identifier is omitted:

int n; // declaration of an int
sizeof(int); // use of type name
 
int *a[3]; // declaration of an array of 3 pointers to int
sizeof(int *[3]); // use of type name
 
int (*p)[3]; // declaration of a pointer to array of 3 int
sizeof(int (*)[3]); // use of type name
 
int (*a)[*] // declaration of pointer to VLA (in a function parameter)
sizeof(int (*)[*]) // use of type name (in a function parameter)
 
int *f(void); // declaration of function
sizeof(int *(void)); // use of type name
 
int (*p)(void); // declaration of pointer to function
sizeof(int (*)(void)); // use of type name
 
int (*const a[])(unsigned int, ...) = {0}; // array of pointers to functions
sizeof(int (*const [])(unsigned int, ...)); // use of type name

Except the redundant parentheses around the identifier are meaningful in a type-name and represent "function with no parameter specification":

int (n); // declares n of type int
sizeof(int ()); // uses type "function returning int"

Type names are used in the following situations:


A type name may introduce a new type:

void* p = (void*)(struct X { int i; } *)0;
// type name "struct X {int i;}*" used in the cast expression
// introduces the new type "struct X"
struct X x = {1}; // struct X is now in scope
[edit] References
[edit] See also

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4