is size_t always unsigned?
Yes. It's usually defined as something like the following (on 32-bit systems):
typedef unsigned int size_t;
Reference:
C++ Standard Section 18.1 defines size_t
is in <cstddef>
which is described in C Standard as <stddef.h>
.
C Standard Section 4.1.5 defines size_t
as an unsigned integral type of the result of the sizeof
operator
Is size_t is always unsigned int
x86-64 and aarch64 (arm64) Linux, OS X and iOS all have size_t
ultimately defined as unsigned long
. (This is the LP64 model. This kind of thing is part of the platform's ABI which also defines things like function calling convention, etc. Other architectures may vary.) Even 32-bit x86 and ARM architectures use unsigned long
on these OSes, although long
happens to be the same representation as an int
in those cases.
I'm fairly sure it's an unsigned __int64
/unsigned long long
on Win64. (which uses the LLP64 model)
Why is size_t unsigned?
size_t
is unsigned for historical reasons.
On an architecture with 16 bit pointers, such as the "small" model DOS programming, it would be impractical to limit strings to 32 KB.
For this reason, the C standard requires (via required ranges) ptrdiff_t
, the signed counterpart to size_t
and the result type of pointer difference, to be effectively 17 bits.
Those reasons can still apply in parts of the embedded programming world.
However, they do not apply to modern 32-bit or 64-bit programming, where a much more important consideration is that the unfortunate implicit conversion rules of C and C++ make unsigned types into bug attractors, when they're used for numbers (and hence, arithmetical operations and magnitude comparisions). With 20-20 hindsight we can now see that the decision to adopt those particular conversion rules, where e.g. string( "Hi" ).length() < -3
is practically guaranteed, was rather silly and impractical. However, that decision means that in modern programming, adopting unsigned types for numbers has severe disadvantages and no advantages – except for satisfying the feelings of those who find unsigned
to be a self-descriptive type name, and fail to think of typedef int MyType
.
Summing up, it was not a mistake. It was a decision for then very rational, practical programming reasons. It had nothing to do with transferring expectations from bounds-checked languages like Pascal to C++ (which is a fallacy, but a very very common one, even if some of those who do it have never heard of Pascal).
unsigned int vs. size_t
The size_t
type is the unsigned integer type that is the result of the sizeof
operator (and the offsetof
operator), so it is guaranteed to be big enough to contain the size of the biggest object your system can handle (e.g., a static array of 8Gb).
The size_t
type may be bigger than, equal to, or smaller than an unsigned int
, and your compiler might make assumptions about it for optimization.
You may find more precise information in the C99 standard, section 7.17, a draft of which is available on the Internet in pdf format, or in the C11 standard, section 7.19, also available as a pdf draft.
Difference between size_t and unsigned int?
if it is use to represent non negative value so why we not using
unsigned int
instead ofsize_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
andunsigned 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.
Can I just use unsigned int instead of size_t?
size_t
is the most correct type to use when describing the sizes of arrays and objects. It's guaranteed to be unsigned and is supposedly "large enough" to hold any object size for the given system. Therefore it is more portable to use for that purpose than unsigned int
, which is in practice either 16 or 32 bits on all common computers.
So the most canonical form of a for
loop when iterating over an array is actually:
for(size_t i=0; i<sizeof array/sizeof *array; i++)
{
do_something(array[i]);
}
And not int i=0;
which is perhaps more commonly seen even in some C books.
size_t
is also the type returned from the sizeof
operator. Using the right type might matter in some situations, for example printf("%u", sizeof obj);
is formally undefined behavior, so it might in theory crash printf or print gibberish. You have to use %zu
for size_t
.
It is quite possible that size_t
happens to be the very same type as unsigned long
or unsigned long long
or uint32_t
or uint64_t
though.
Where do I find the definition of size_t?
From Wikipedia
The
stdlib.h
andstddef.h
header files define a datatype calledsize_t
1 which is used to represent the size of an object. Library functions that take sizes expect them to be of typesize_t
, and the sizeof operator evaluates tosize_t
.The actual type of
size_t
is platform-dependent; a common mistake is to assumesize_t
is the same as unsigned int, which can lead to programming errors,2 particularly as 64-bit architectures become more prevalent.
From C99 7.17.1/2
The following types and macros are defined in the standard header
stddef.h
<snip>
size_t
which is the unsigned integer type of the result of the sizeof operator
Was `long` guaranteed to be as wide as `size_t`
There is no such guarantee.
While it is common for implementation to have same size for long
and size_t
, it is not always the case. As put in the comments Windows 64-bit have different size for long
and size_t
.
Also notice that the minimum value of SIZE_MAX
for an implementation is 65535
while the minimum value of ULONG_MAX
is 4294967295
(2147483647
for LONG_MAX
). (Note that SIZE_MAX
appeared with C99.) It means that size_t
is guaranteed to be at least 16-bit but unsigned long
/ long
are guaranteed to be at least 32-bit.
EDIT: Question has changed a little bit after this answer... So:
So the question is could you assume or were you guaranteed that long were enough to hold size_t in pre C99.
There is no such guarantee even in C89. long
can be 32-bit and size_t
64-bit. (See C89 example with MSVC in Windows 64-bit above.)
The other question is whether there exists any guarantee that size_t would fit in any of the other standardized integer types (except the obvious exceptions like ssize_t, ptrdiff_t and such).
Again there is no such guarantee by the Standard. size_t
is an alias for another standard unsigned integer type (and it cannot be an extended integer type as C89 does not have extended integer types).
What is size_t in C?
From Wikipedia:
According to the 1999 ISO C standard
(C99),size_t
is an unsigned integer
type of at least 16 bit (see sections
7.17 and 7.18.3).
size_t
is an unsigned data type
defined by several C/C++ standards,
e.g. the C99 ISO/IEC 9899 standard,
that is defined instddef.h
.1 It can
be further imported by inclusion of
stdlib.h
as this file internally sub
includesstddef.h
.This type is used to represent the
size of an object. Library functions
that take or return sizes expect them
to be of type or have the return type
ofsize_t
. Further, the most
frequently used compiler-based
operator sizeof should evaluate to a
constant value that is compatible with
size_t
.
As an implication, size_t
is a type guaranteed to hold any array index.
Can sizeof(size_t) be less than sizeof(int)?
Yes, sizeof(size_t)
can, in principle, be less than sizeof(int)
. I don't know of any implementations where this is true, and it's likely that there are none. I can imagine an implementation with 64-bit int
and 32-bit size_t
.
But indexing an array with unsigned int
is safe -- as long as the value of the index is within the bounds imposed by the length of the array. The argument to the []
operator is merely required to be an integer. It's not converted to size_t
. It's defined in terms of pointer arithmetic, in which the +
operator has one argument that's a pointer and another argument that is of any integer type.
If unsigned int
is wider than size_t
, then an unsigned int
index value that exceeds SIZE_MAX
will almost certainly cause problems because the array isn't that big. In C++14 and later, defining a type bigger than SIZE_MAX
bytes is explicitly prohibited (3.9.2 [compound.types] paragraph 2; section 6.9.2 in C++17). In earlier versions of C++, and in all versions of C, it isn't explicitly prohibited, but it's unlikely that any sane implementation would allow it.
Related Topics
How to Enable_Shared_From_This of Both Parent and Derived
How to Merge Two Bst's Efficiently
C++ Best Way to Get Integer Division and Remainder
Add External Libraries to Cmakelist.Txt C++
Get Size of Terminal Window (Rows/Columns)
Image Edge Smoothing with Opencv
Is There a Compact Equivalent to Python Range() in C++/Stl
Std::Vector Reserve() and Push_Back() Is Faster Than Resize() and Array Index, Why
Should I Use Public or Private Variables
Using Declaration in Variadic Template
C++ Trying to Swap Values in a Vector
Why Was Pair Range Access Removed from C++11
Vc++ Fatal Error Lnk1168: Cannot Open Filename.Exe for Writing
Broken C++ Std Libraries on MACos High Sierra 10.13
How to Track Memory Allocations in C++ (Especially New/Delete)