should use size_t or ssize_t
Solution 1
ssize_t
is used for functions whose return value could either be a valid size, or a negative value to indicate an error.
It is guaranteed to be able to store values at least in the range [-1, SSIZE_MAX]
(SSIZE_MAX
is system-dependent).
So you should use size_t
whenever you mean to return a size in bytes, and ssize_t
whenever you would return either a size in bytes or a (negative) error value.
See: http://pubs.opengroup.org/onlinepubs/007908775/xsh/systypes.h.html
Solution 2
ssize_t
is not included in the standard and isn't portable. size_t
should be used when handling the size of objects (there's ptrdiff_t
too, for pointer differences).
Related videos on Youtube
hgyxbll
Updated on April 21, 2020Comments
-
hgyxbll about 4 years
At my code, I do not use int or unsigned int. I only use size_t or ssize_t for portable. For example:
typedef size_t intc; // (instead of unsigned int) typedef ssize_t uintc; // (instead of int)
Because
strlen
,string
,vector
... all usesize_t
, so I usually usesize_t
. And I only usessize_t
when it may be negative.But I find that:
The unsigned integer types are ideal for uses that treat storage as a bit array. Using an unsigned instead of an int to gain one more bit to represent positive integers is almost never a good idea. Attempts to ensure that some values are positive by declaring variables unsigned will typically be defeated by the implicit conversion rules.
in the book The C++ Programming Language.
So I am puzzled. Am I wrong? Why does the STL not abide by the suggest on the book?
-
kassak about 11 years
size_t
used in standart library for representing sizes. It would be strange if the size of container could be negative. Interface states it's behavior. I think book assumes day-to-day usage, not interface -
Bo Persson about 11 years@kassak - No, in this case an unsigned type actually is used to get one extra bit for the value. Some members of the committee saw it important to be able to have a
std::vector<char>
larger than half the available memory. And the quote says "almost never"... -
hgyxbll about 11 years@Bo Persson, thanks, C++ lib use size_t for range. But it brought us the trouble. If we use int, we must be carefull to compare them.
-
chux - Reinstate Monica over 8 yearsNominate for re-opening as the duplicate cited does not address this post close enough.
-
RastaJedi over 7 yearsUsing
intc
for unsignedsize_t
(as you say, '[signed]int
' in comment, even though it's probably longer), anduintc
for signedssize_t
('unsigned int
' in comment), is confusing to me, because normally the 'u' stands for unsigned, e.g.uint32_t
is the unsigned version ofint32_t
, a 4-byte integer. -
EnzoR over 6 yearsTo those who marked as duplicate. This is definitely not a duplicate. The question is not about signed vs unsigned, but size_t vs ssize_t, that is "when should I use either"?
-
Павел almost 4 yearsfor (size_t i = a; i < b; i += 2), how many iterations?, a = 0, b = 0xffffffff (32-bit pointers) => infinity loop, for (ssize_t i = a; i < b; i+= 2), how many iterations? (b - a + 1)/2 or none (in case b <= a). Why so? By standart unsigned overflow is well defined and signed overflow is UB (undefined behavior). Compilers some times use UB for optimizations (they assume that several UBs never happen). Some optimizations need to calculate number of loop iterations. From such point of view signed counters is preferrable.
-
hgyxbll about 3 yearsnow I always use 'int' for most cases, because 'int' is natural, and default a digit's type is 'int', and the range of 'int' is enough for me.
-
-
hgyxbll about 11 yearsI have used ssize_t instead of int. Because CPU handle fast with ssize_t when it is x64.
-
AnT stands with Russia over 9 yearsWell, this answer fails to fully explain the consequences of basing such decisions on pure interface considerations. It is unlikely that any implementation will use wider type for
ssize_t
than it uses forsize_t
. This immediately means that the price you will pay for the ability to return negative values is halving of the positive range of the type. I.e.SSIZE_MAX
is usuallySIZE_MAX / 2
. This should be kept in mind. In many cases this price is not worth paying just for the ability to return-1
as a negative value. -
thesaint about 9 years@AnT having unsigned values at all is one of the greatest failures in C++. There is no case where the price is not worth paying. If you need such large numbers, use int64_t instead...
-
josaphatv over 8 years@thesaint What the heck are you talking about? It's not about capacity. How would you add four to the stack pointer if its current value may or may not be negative?
-
thesaint over 8 years@josaphatv What? How would you add four to the value of the stack pointer if you don't know if that would overflow it? Not to mention that the whole phrase of "adding for to the stack pointer" has nothing to do with C++. Unsigned values are bad because 1) They cause type conversion issues all over the place 2) They add absolutely no benefit 3) They are even less intuitive and predictable than signed ints, since they overflow already at zero. And expression like "while(some_uint - 1 >= 0)" is wrong and hard to spot. Signed overflows are much less likely.
-
thesaint over 8 yearsBesides that your statement makes absolutely no sense. Adding a number to either int or uint is only a matter of wether or not it overflows. If the stack pointer was indeed negative then you have a different problem lol. And even if so, adding something doesn't inherently break anything. Something was broken before. How you think this is any worse than adding four to 0x7FFFFFFF is beyond me (which overflows into kernel space => BOOM).
-
xis over 8 years@hgyxbll What do you mean by ssize_t is faster than int? ssize_t can be either int, or long, it would not be an actual type. I could not understand this, please explain.
-
SlySven over 8 yearsDidn't unsigned integers come about first (prior to signed ones) because of the hardware - obviously this is closer to bare-metal C than most C++ usage but the use of the MSB to allow signed arithmetic was not done just to halve the absolute magnitude that a "integer" could represent but because there was a need for subtractive maths. signed ints and unsigned ints are pears and apples - different but able to cross under certain, limited circumstances...! (Half of the range of each is shared.)
-
SlySven over 8 yearsWhere the confusion seems to arise, to me, is when a function that seems it should produce only an unsigned value i.e. the number of bytes that
read(2)
has been able to actually read. However in the case of an error the value of -1 (probably encoded as ALL bits set) is returned - not to make things difficult but because it is a sentinel value that cannot arise normally. -
Justin Time - Reinstate Monica over 7 years@thesaint Conversely, if a value cannot be lower than 0, allowing it to be signed is a failure to communicate intent. You can't logically have an array, or other container, of -10
char
s, for example (logically, a container with negative size would require the power of creation, because it's so small that it actually increases the number of uncontained objects in its vicinity, creating new ones out of nothing), so it wouldn't make sense to use a signed type for array bounds instead of an unsigned one. -
Justin Time - Reinstate Monica over 7 yearsThe problem with unsigned types isn't that they exist, it's that they're considered and treated as integers (since all integers, by mathematical definition, are signed); this is directly responsible for people treating them the same as signed types, and by extension for all the problems associated with them. Unsigned types are inherently more predictable (due to having defined overflow behaviour), but a lot of people completely fail to take it into account when checking them because they're used to signed counters (which, IMO, is a failure at teaching, when the counter cannot be less than 0).
-
Justin Time - Reinstate Monica over 7 yearsInstead of
while(some_uint - 1 >= 0)
orfor(some_uint = 10; some_uint >= 0; --i)
, a proper check that takes unsigned properties into account would look something likewhile(some_uint != 0)
orfor(some_uint = 10; some_uint + 1 != 0; --some_uint)
. This loop condition works properly regardless of the loop counter's signedness: It ends the loop whensome_uint
reaches-1
, (which is a valid value for signed types, and equal to the maximum storeable value for unsigned types due to overflow/underflow rules); regardless of signedness,-1 + 1
must always equal0
. -
Justin Time - Reinstate Monica over 7 yearsThe
while
loop works because: Forsome_uint - 1
to be>= 0
,some_uint
must logically be>= 1
; therefore, oncesome_uint == 0
, and is thus no longer>= 1
,some_uint - 1
can no longer be>= 0
, and the loop is terminated. Thefor
loop works on the same principle: Forsome_uint
to be>= 0
,some_uint + 1
must be>= 1
; therefore, oncesome_uint + 1 == 0
, and is thus no longer>= 1
,some_uint
can no longer be>= 0
, and the loop is terminated. Simple, well-defined, and makes perfect sense if one knows how unsigned types work. -
Justin Time - Reinstate Monica over 7 yearsAlternatively, it could be written to specifically check for
static_cast<decltype(some_uint)>(-1)
; this is more verbose, but communicates intent more clearly. -
Kafu over 7 yearsssize_t is from POSIX: pubs.opengroup.org/onlinepubs/009696799/basedefs/sys/…
-
dtouch3d over 7 yearsThe type ssize_t has a range of [-SSIZE_MAX, SSIZE_MAX], not [-1, SSIZE_MAX].
-
Patrick Fromberg about 4 yearsSupporters of unsigned sizes do not understand two things. One is, that they implicitly advocate for unsigned arithmetic which is totally broken for calculating sizes (also in terms of perforamance). The second thing they may not understand is a bit more subtle (to complicated for me I admit) but here is an example. In transportation they give negative waiting times for events all the time. Negative waiting times are not an error in this case but a useful concept similar to imaginary numbers. BTW, not sure, but was there ever a discussion about negative numbers in book keeping?
-
Swift - Friday Pie almost 4 yearsC++11 and later implements template
std::make_signed
, but it's somewhat grey area if usingsize_t
as its parameter is well-defined. In c++20 use of this template with types not allowed by standard results in ill-formed code, but existing implementations allow use ofsize_t
-
Tom Lint over 2 years@PatrickFromberg what's broken about using unsigned arithmetic for calculating sizes? I've never seen a negative size. You?
-
Patrick Fromberg over 2 years@TomLint, what is broken is that 1-2 equals some hardware dependent arbitrary looking number when using arithmetic operators on unsigned numbers. There are some exotic uses for that, but most of the time this is not the result that you want.
int main () {unsigned int a = 1, b = 2; std::cout << (a-b) << std::endl;}