183

What are the differences between size_t and std::size_t in terms of where they are declared, when they should be used and any other differentiating features?

Artem Klevtsov
  • 9,193
  • 6
  • 52
  • 57
Mankarse
  • 39,818
  • 11
  • 97
  • 141

3 Answers3

115

C's size_t and C++'s std::size_t are both same.

In C, it's defined in <stddef.h> and in C++, its defined in <cstddef> whose contents are the same as C header (see the quotation below). Its defined as unsigned integer type of the result of the sizeof operator.

C Standard says in §17.7/2,

size_t which is the unsigned integer type of the result of the sizeof operator

And C++ Standard says (about cstddef header) in §18.1/3,

The contents are the same as the Standard C library header , with the following changes.

So yeah, both are same; the only difference is that C++ defines size_t in std namespace.

Please also notice that the above line also says "with the following changes" which isn't referring to size_t. Its rather referring to the new additions (mostly) made by C++ into the language (not present in C) which are also defined in the same header.


Wikipedia has very good info about range and storage size of size_t:

Range and storage size of size_t

The actual type of size_t is platform-dependent; a common mistake is to assume size_t is the same as unsigned int, which can lead to programming errors,[3][4] when moving from 32 to 64-bit architecture, for example.

According to the 1999 ISO C standard (C99), size_t is an unsigned integer type of at least 16 bits.

And the rest you can read from this page at wikipedia.

TheBuzzSaw
  • 8,648
  • 5
  • 39
  • 58
Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • 2
    Thats brings to another Q, If STL already imports size_t through C (cstddef) the why it has its own another version again? – Alok Save Apr 28 '11 at 04:51
  • 49
    @Als: Strictly speaking, it is an error to say `size_t` without `using namespace std;` or `using std::size_t;`. However, most compilers allow it, and the Standard specifically allows them to allow it (§D.5/3). – Potatoswatter Apr 28 '11 at 05:03
  • 10
    @Potatoswatter: Surely it can't be both an error and specifically allowed in the standard? If it's in the standard, it's not an error! – Ben Hymers Jul 30 '13 at 13:20
  • 11
    @BenHymers The standard specifies what the standard headers declare, and they are not allowed to declare any other non-reserved names. The header `` may or may not declare `::size_t`, so you cannot rely on it being there or being absent, unless specifically including `` or another header from the C library which is guaranteed to declare it. – Potatoswatter Jul 30 '13 at 23:48
  • 5
    @Potatoswatter: Ah, I see what you mean now! I must have gotten confused by too many "allow"s in one sentence. I still think your first comment is too strong though; as you just said, `::size_t` is present e.g in ``, so you don't always need to qualify it with `std::`. – Ben Hymers Jul 31 '13 at 08:28
19

From C++03 "17.4.3.1.4 Types":

For each type T from the Standard C library (footnote 169), the types ::T and std::T are reserved to the implementation and, when defined, ::T shall be identical to std::T.

And footnote 169:

These types are clock_t, div_t, FILE, fpos_t, lconv, ldiv_t, mbstate_t, ptrdiff_t, sig_atomic_t, size_t, time_t, tm, va_list, wctrans_t, wctype_t, and wint_t.

Michael Burr
  • 333,147
  • 50
  • 533
  • 760
  • So portable code shouldn't rely on the `std::T` variants being defined? – Mankarse Apr 28 '11 at 05:24
  • 6
    @Mankarse: You shouldn't rely on them being defined *if* you only include the C version of the corresponding header. If you `#include ` then `std::size_t` might or might not be available. If you `#include ` then `std::size_t` is available, but `size_t` might not be. – Dennis Zickefoose Apr 28 '11 at 05:46
  • 5
    @Mankarse: The oposite. The C++ versions of the headers must define them in `std::` and the paragraph says that it may also define them in top-level namespace and if it does, it must define them identically in `std::` and top-level. Most compilers just include the C header and import the names to `std::`, so the symbols do end up defined in both. – Jan Hudec Apr 28 '11 at 06:32
  • 4
    Personally, I never bother with the headers or the `std::` variants of identifiers that come from the C shore. I stick with `` for the standard C headers - it's never been a problem. So, I'd use `` and `size_t` and never give a second thought to `std::size_t`; in fact, it never crosses my mind that there is (or might be) a `std::size_t`. – Michael Burr Apr 28 '11 at 06:32
17

std::size_t is in fact stddef.h's size_t.

cstddef gives the following:

#include <stddef.h>
namespace std 
{
  using ::ptrdiff_t;
  using ::size_t;
}

...effectively bringing the previous definition into the std namespace.

Edgar Rokjān
  • 17,245
  • 4
  • 40
  • 67
hifier
  • 457
  • 3
  • 9
  • As Nawaz points out, it's actually the other way around. You can't include `` and expect to get `::size_t`, but if you include `` you will get `std::size_t`. – MSalters Apr 28 '11 at 08:40
  • 4
    @MSalters, I don't follow. Including `` will only get you `::size_t`. – hifier May 01 '11 at 16:23
  • 2
    That is a bug in your implementation, then. – MSalters May 02 '11 at 10:47
  • 4
    @MSalters, I don't quite follow. Shouldn't it be the other way round? comes from C++, thus should define the stuff in std::*? On the other hand, in a C header, like stddef.h, I would only expect the C type, i.e. ::size_t. – Ela782 Nov 18 '14 at 00:58
  • 14
    @MSalters, since C++11 that's not accurate. If you include `` you are guaranteed to get `std::size_t` and you might also get `::size_t` (but it's not guaranteed). If you include `` you're guaranteed to get `::size_t` and you might also get `std::size_t` (but it's not guaranteed). It was different in C++03 but that was effectively unimplementable and fixed as a defect. – Jonathan Wakely Nov 12 '16 at 23:22
  • This answer is outright incorrect. This is an assumption about the implementation that other implementations may not adhere too. The standard specifically states that `cstddef` will define `std::size_t`, but it may or may not introduce `::size_t` (it neither requires nor prohibits it0. Even if the implementation does introduce `::size_t`, that could be done either through placing a `using ::size_t;` into `namespace std` or placing a `using std::size_t;` into the global namespace, there's no way of guaranteeing which method an implementation will do it. – Pharap Dec 04 '19 at 23:15