149

I am so confused about size_t. I have searched on the internet and everywhere mentioned that size_t is an unsigned type so, it can represent only non-negative values.

My first question is: if it is used to represent only non-negative values, why don't we use unsigned int instead of size_t?

My second question is: are size_t and unsigned int interchangeable or not? If not, then why?

And can anyone give me a good example of size_t and briefly its workings?

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
Vikas Verma
  • 3,626
  • 6
  • 27
  • 40
  • 7
    `typedef /*This part is implementation dependent */ size_t; ` – P0W Nov 01 '13 at 17:50
  • 5
    possible duplicate of [unsigned int vs. size\_t](http://stackoverflow.com/questions/131803/unsigned-int-vs-size-t) –  Mar 27 '14 at 09:51

7 Answers7

120

if it is use to represent non negative value so why we not using unsigned int instead of size_t

Because unsigned int is not the only unsigned integer type. size_t could be any of unsigned char, unsigned short, unsigned int, unsigned long or unsigned long long, depending on the implementation.

Second question is that size_t and unsigned int are interchangeable or not and if not then why?

They aren't interchangeable, for the reason explained above ^^.

And can anyone give me a good example of size_t and its brief working ?

I don't quite get what you mean by "its brief working". It works like any other unsigned type (in particular, like the type it's typedeffed to). You are encouraged to use size_t when you are describing the size of an object. In particular, the sizeof operator and various standard library functions, such as strlen(), return size_t.

Bonus: here's a good article about size_t (and the closely related ptrdiff_t type). It reasons very well why you should use it.

Santhosh Kumar
  • 543
  • 8
  • 22
  • 1
    How exactly can `size_t` be a `unsigned char`? Is this in the standard that it's allowed? I mean with that idea how could anyone be expected to use `calloc()` (and family), `strlen()` etc.? That seems to me absurd. – Pryftan Nov 17 '19 at 20:35
  • 1
    I think `size_t` is defined in the standard to be an "unsigned integer type", but doesn't require it to be the same as any of `unsigned {char, short, int, long, long long}`. – Paul Hankin Jun 13 '20 at 07:40
  • @Pryftan, for example an 8-bit architecture would use ``unsigned char`` as `size_t`. You don't need to worry about what `size_t` will be, compilers takes care of it depending on the target architecture. – Ekrem Dinçel Nov 10 '20 at 17:13
  • "the memory size (in bytes) of the size_t is decided by the compiler. The compiler (somehow) determines the most suitable unsigned integer datatype which can hold the largest possible arraysize (of 1 byte/smallest unit of memory) that the architecture/hardware can support and typedef it as **size_t**" - please validate the truthness of my statement. –  Dec 23 '21 at 09:14
113

There are 5 standard unsigned integer types in C:

  • unsigned char
  • unsigned short
  • unsigned int
  • unsigned long
  • unsigned long long

with various requirements for their sizes and ranges (briefly, each type's range is a subset of the next type's range, but some of them may have the same range).

size_t is a typedef (i.e., an alias) for some unsigned type, (probably one of the above but possibly an extended unsigned integer type, though that's unlikely). It's the type yielded by the sizeof operator.

On one system, it might make sense to use unsigned int to represent sizes; on another, it might make more sense to use unsigned long or unsigned long long. (size_t is unlikely to be either unsigned char or unsigned short, but that's permitted).

The purpose of size_t is to relieve the programmer from having to worry about which of the predefined types is used to represent sizes.

Code that assumes sizeof yields an unsigned int would not be portable. Code that assumes it yields a size_t is more likely to be portable.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • 8
    I think this should be the accepted answer because it explains why you should use size_t – kuchi Aug 31 '16 at 00:10
  • @keith-thompson so does this mean that the specific type (i.e. `unsigned int`, `unsigned long`, etc.) that `size_t` corresponds to depends on the machine on which the code is run? i.e. on one machine architecture, it corresponds to `unsigned int` but on another architecture it will correspond to `unsigned long`, etc? – Richie Thomas Nov 05 '19 at 17:43
  • 1
    @RichieThomas: It depends on the C implementation. Two different compilers on the same architecture might choose different types for `size_t`, especially if, for example, `unsigned long` and `unsigned long long` are the same size. – Keith Thompson Nov 05 '19 at 20:15
  • @RichieThomas That's part of it too. That is to say that the max of `long`, `long long` etc. do depend on the system: If you take a look at `limits.h` you will at least under Unices see that the max value for ints depends on the word size of the system. – Pryftan Nov 17 '19 at 21:44
  • @Pryftan: It's not entirely clear what either "the system" or "word size" really means. For example, on exactly the same hardware, Windows implementations will typically have 32-bit `long` and Unix-like (including Linux-based) implementations will typically have 64-bit `long. x86-64 (x64) systems have a word size of 64 bits, but `int` is almost always 32 bits. All those choices are ultimately up to the C implementation, specifically the compiler. The compiler's choice is likely to be guided by an ABI. – Keith Thompson Nov 17 '19 at 22:50
  • @KeithThompson Well I didn't know the Windows part but yes you're right - I won't deny that at all. I would also expect `sizeof int == 4` indeed. I don't know what makes the compiler decide but I suspect it's more than just the word size as you say; I am as I noted only speaking on a Unix basis and admittedly it's been decades since I used anything but Linux! I will argue though that word size is clear: it's just how it's used wrt the sizeof integers might not be. Or are you saying that too? Anyway interesting what you say about Windows and all the more relevant to the post! Cheers. – Pryftan Nov 19 '19 at 12:26
  • @Pryftan: `int` has remained 32 bits in most implementations for backward compatibility and to ensure that there are integer types of 8, 16, and 32 bits. Making `char` 8 bits and `int` 64 bits (which would be "natural" on many CPUs) would mean `short` could be either 16 or 32 bits, and there would be no fundamental type of the other size. (C99 introduced *extended integer types*, but they're rarely implemented.) There have been CPUs in which the word size is unclear, for example in families of CPUs transitioning from 16 to 32 or 32 to 64. – Keith Thompson Nov 19 '19 at 18:15
  • @KeithThompson Well I didn't know the 'why' wrt portability and I certainly didn't know about specific CPUs that have unclear word sizes. That's interesting. I won't trigger the website here complaining about 'chat' so don't worry about telling me what CPUs - I have too much going on to consider it much anyway. Thanks for the interesting titbits. – Pryftan Nov 19 '19 at 20:42
  • 1
    @Pryftan Take a look at the Motorola 68000 series, also the older Intel x86 series (going back to the 8086 and 8088). – Keith Thompson Nov 19 '19 at 20:46
12

size_t has a specific restriction.

Quoting from http://www.cplusplus.com/reference/cstring/size_t/ :

Alias of one of the fundamental unsigned integer types.

It is a type able to represent the size of any object in bytes: size_t is the type returned by the sizeof operator and is widely used in the standard library to represent sizes and counts.

It is not interchangeable with unsigned int because the size of int is specified by the data model. For example LLP64 uses a 32-bit int and ILP64 uses a 64-bit int.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
DrYap
  • 6,525
  • 2
  • 31
  • 54
11

Apart from the other answers it also documents the code and tells people that you are talking about size of objects in memory

Ed Heal
  • 59,252
  • 17
  • 87
  • 127
7

size_t is used to store sizes of data objects, and is guaranteed to be able to hold the size of any data object that the particular C implementation can create. This data type may be smaller (in number of bits), bigger or exactly the same as unsigned int.

Thomas Padron-McCarthy
  • 27,232
  • 8
  • 51
  • 75
2

size_t type is a base unsigned integer type of C/C++ language. It is the type of the result returned by sizeof operator. The type's size is chosen so that it could store the maximum size of a theoretically possible array of any type. On a 32-bit system size_t will take 32 bits, on a 64- bit one 64 bits. In other words, a variable of size_t type can safely store a pointer. The exception is pointers to class functions but this is a special case. Although size_t can store a pointer, it is better to use another unsigned integer type uintptr_t for that purpose (its name reflects its capability). The types size_t and uintptr_t are synonyms. size_t type is usually used for loop counters, array indexing and address arithmetic. The maximum possible value of size_t type is constant SIZE_MAX .

  • 2
    `size_t` can store the size of any single object. A pointer can point to any byte of any object. You can have a system with, for example, a 64-bit address space that limits the size of any one object to 2**32-1 bytes. There is no guarantee that `size_t` and `uintptr_t` are the same type. – Keith Thompson Dec 26 '14 at 22:17
2

In simple words size_t is platform and as well as implementation dependent whereas unsigned int is only platform dependent.