Names specified here
Name Description Notes Source Availability
offsetof() Determine structure-member position L M (·) <stddef.h> C89 C90 C95 C99 C11
struct Introduces structure type L Keyword C89 C90 C95 C99 C11

C allows groups of related objects to be handled as a unit called a structure. The keyword struct introduces a structure type which can then be used to declare objects of that type. For example, the following declaration defines a new type called struct point, which has two members, x and y, both of type int:

struct point {
  int x;
  int y;
};

The name of the type is struct point, not point, which is just the type's tag, and could safely identify another object or a distinct type.

Members of a structure type can be of any complete type. With the above declaration in place, variables now can be declared of type struct point, and individual members can be accessed using the operator .:

struct point a, b;

a.x = 10;
a.y = 20;
b.x = -a.y;
b.y = a.x;
postfix-expression
postfix-expression . identifier
Structures and Unions

It's also possible to list initial values for a structure when it is defined:

struct point a = { 10, 20 };
struct point b = { -a.y, a.x };

It is an error if there are more values than members. If there are too few, remaining members are zero-initialized. From C99, specific members can be initialized in any order:

struct point a = { .x = 10, .y = 20 };
struct point b = { .y = a.x, .x = -a.y };

Structures can be passed to and returned from functions:

struct point add_points(struct point p1,
                        struct point p2)
{
  p1.x += p2.x;
  p1.y += p2.y;

  return p1;
}

As parameters, they are ordinary copies of whatever was passed to them, so it is safe for the function to modify its own copies, as above. However, structures can be very large, and passing copies of them as function arguments, and returning them too, can incur a large overhead. Therefore, it is very common to see them passed by reference using a pointer. For example, this function would usually be considered more efficient than the one above:

void add_points(struct point *out,
                struct point *p1,
                struct point *p2)
{
  (*out).x = (*p1).x + (*p2).x;
  (*out).y = (*p1).y + (*p2).y;
}

Note that the pointer-dereference operator * has lower precedence than the member-access operator ., so additional brackets are necessary. Because structures are almost always used with pointers, another operator is provided ->, which combines the dereferencing and member access in one. This allows us to rewrite the function more aesthetically:

void add_points(struct point *out,
                struct point *p1,
                struct point *p2)
{
  out->x = p1->x + p2->x;
  out->y = p1->y + p2->y;
}
postfix-expression
postfix-expression -> identifier
Structures and Unions

As the function does not and should not modify its inputs, we can use const on them:

void add_points(struct point *out,
                const struct point *p1,
                const struct point *p2)
{
  out->x = p1->x + p2->x;
  out->y = p1->y + p2->y;
}

The definition of a structure type can be combined with a declaration of an object of that type:

struct point {
  int x;
  int y;
} p1, p2, p3;

In fact, a structure-type definition is an object declaration, but object declarations need not actually declare any objects. This means that the following declaration is not only bizarre and pointless, but also legal!:

int;

Objects can be of anonymous structure type too. This is useful in a few circumstances. One is when declaring an object with the type definition:

struct {
  double length;
  int counter;
  // etc.
} foo;

Such an object obviously can't be passed to a function without losing its type information.

Another use of an anonymous type is with a type alias, such as:

typedef struct {
  int x;
  int y;
} point;

As with all typedefs, the new type name sits where a variable name would be if the typedef keyword were to be removed. This structure type is innately anonymous, but the alias will work as expected, allowing us to declare functions more compactly:

void add_points(point *out, const point *p1, const point *p2)

The structure types shown so far are all complete. As such, you can declare arrays of structures, unions of structures, and even structures of structures. For example:

struct rect {
  struct point min, max;
};

So it's not uncommon for members of a named structure type to be of anonymous types, used only for grouping related members together.

Structure types can be incomplete too:

struct point;

This is sufficient to declare something that uses pointers to the structure type:

// okay
void add_points(struct point *out,
                const struct point *p1,
                const struct point *p2)

…but not something that depends on the whole structure, such as that function's definition, or a declaration of the alternative function that doesn't use pointers:

// error
struct point add_points(struct point p1,
                        struct point p2);

In such cases, the complete structure type must first be visible. It's legal to declare an incomplete type, and then complete it later:

struct point;

// Okay
struct point {
  int x, y;
};

It is illegal to complete the type twice in the same translation unit, even if the definitions are identical:

// Okay
struct point {
  int x, y;
};

// Error
struct point {
  int x, y, z;
};

// Error
struct point {
  int x, y;
};

An incomplete structure type also can't appear directly in its own definition:

struct foo {
  struct foo inner; // error
};

The definition of struct foo is incomplete until the end of its definition, so it can't be used until after the closing brace }. In any case, this recursive definition would imply that the structure had infinite size! An alternative using pointers is permitted:

struct elem {
  struct elem *next;
  char *text;
};

…because struct elem * is a complete type, even if struct elem is not (yet). Such structure types are commonly used to form complex data structures (in the more general sense of ‘structure’) such as linked lists and binary trees.

From C99, a structure type can end with a member of array type with unspecified length. For example:

struct foo {
  int bar;
  double baz;
  size_t sz;
  T buff[];
};

The size of a structure of this type with n trailing elements is given by sizeof(struct foo) + n * sizeof(T), for any complete type T.

The alignment of members of a structure type can be configured with alignas.

If a structure has an address, then each of its members can have an address too. The address-of operator & has lower precedence than . or ->, so an expression such as &p1->x will give us the address of the member x as expected.

#include <stddef.h>
size_t offsetof(struct-type, struct-member);

The macro offsetof will give the relative position of a structure member within its type, e.g., offsetof(struct point, y).

Structure types can include bitfields, integer members of a specific width. For example:

struct header {
  unsigned type : 4;
  unsigned route : 1, urgent : 1, ext : 1;
};

Such bitfields do not have addresses. How they pack into the underlying bytes of the structure, including their order and padding, is implementation-defined. A bitfield of width 0, which can also be anonymous, can indicate that the next member should be aligned on some implementation-defined boundary.

Structures are often dynamically allocated:

struct point *ptr = malloc(sizeof *ptr);

Such a structure must be deallocated as a unit too:

free(ptr);

It's not possible to deallocate an individual member of a structure:

free(&ptr->y); // error
Standard structure types
Name Description Notes Source Availability
div_t Result of integer division T <stdlib.h> C89 C90 C95 C99 C11
imaxdiv_t Result of integer division T <inttypes.h> C99 C11
ldiv_t Result of integer division T <stdlib.h> C99 C11
lldiv_t Result of integer division T <stdlib.h> C99 C11
struct lconv Description of local notations T <locale.h> C89 C90 C95 C99 C11
struct timespec Nanosecond time type T <time.h> C11
struct tm Time type T Headers C89 C90 C95 C99 C11
type-specifier
struct-or-union-specifier
struct-or-union-specifier
struct-or-union identifieropt { struct-declaration-list }
struct-or-union identifier
struct-or-union
struct
struct-declaration-list
struct-declaration
struct-declaration-list struct-declaration
struct-declaration
specifier-qualifier-list struct-declarator-listopt ;
static_assert-declaration
since C11
specifier-qualifier-list
type-specifier specifier-qualifier-listopt
type-qualifier specifier-qualifier-listopt

CHaR
Sitemap Supported
Site format updated 2024-06-05T22:37:07.391+0000
Data updated 1970-01-01T00:00:00.000+0000
Page updated 2022-06-17T21:43:05.000+0000