Which header should I include for `size_t`?

Assuming I wanted to minimize the functions and types I was importing I'd go with cstddef as it doesn't declare any functions and only declares 6 types. The others focus on particular domains (strings, time, IO) that may not matter to you.

Note that cstddef only guarantees to define std::size_t, that is, defining size_t in namespace std, although it may provide this name also in the global namespace (effectively, plain size_t).

In contrast, stddef.h (which is also a header available in C) guarantees to define size_t in the global namespace, and may also provide std::size_t.


In fact the synopsis (included in the C++ standard) of several headers specifially include size_t as well as further headers define the type size_t (based on the C standard as the <cX> headers are just ISO C <X.h> headers with noted changes where removal of size_t is not indicated).

The C++ standard however, refers to <cstddef> for the definition of std::size_t

  • in 18.2 Types,
  • in 5.3.3 Sizeof,
  • in 3.7.4.2 Deallocation functions (which refers to 18.2) and
  • in 3.7.4.1 Allocation functions (also refers to 18.2).

Therefore and because of the fact that <cstddef> only introduces types and no functions, I'd stick to this header to make std::size_t available.


Note a few things :

  1. The type of std::size_t is obtainable using decltype without including a header

    If you're planning to introduce a typedef in your code anyway (i.e. because you write a container and want to provide a size_type typedef) you can use the global sizeof, sizeof... or alignof operators to define your type without including any headers at all since theose operators return std::size_t per standard definition and you can use decltype on them:

    using size_type = decltype(alignof(char));
    
  2. std::size_t is not per se globally visible although functions with std::size_t arguments are.

    The implicitly declared global allocation and deallocation functions

    void* operator new(std::size_t);
    void* operator new[](std::size_t);
    void operator delete(void*);
    void operator delete[](void*);
    

    do NOT introduce size_t, std or std::size_t and

    referring to std or std::size_t is ill-formed unless the name has been declared by including the appropriate header.

  3. The user may not redefine std::size_t although it is possible to have multiple typedefs referring to the same type in the same namespace.

    Although, the occurrence of multiple definitions of size_t within std is perfectly valid as per 7.1.3 / 3, it is not allowed to add any declarations to namespace std as per 17.6.4.2.1 / 1:

    The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified.

    Adding a proper typedef for size_t to the namespace does not violate 7.1.3 but it does violate 17.6.4.2.1 and leads to undefined behaviour.

    Clarification: Try not to misinterpret 7.1.3 and do not add declarations or definitions to std (except a few template specialization cases where a typedef is not a template specialization). Extending the namespace std