finding max value of size_t

  • Thread starter subramanian100in
  • Start date
S

subramanian100in

Consider the following program

#include <limits.h>
#include <stddef.h>

int main(void)
{
size_t size;
size_t bytes = sizeof(size_t);

if (bytes == sizeof(unsigned int))
size = UINT_MAX;
else if (bytes == sizeof(unsigned long))
size = ULONG_MAX;
else if (bytes == sizeof(unsigned long long))
size = ULLONG_MAX;

return 0;
}

Can this code give the maximum value of size_t in all standard C
compliant compilers.
 
R

Richard Heathfield

(e-mail address removed), India said:
Consider the following program

#include <limits.h>
#include <stddef.h>

int main(void)
{
size_t size;
size_t bytes = sizeof(size_t);

if (bytes == sizeof(unsigned int))
size = UINT_MAX;
else if (bytes == sizeof(unsigned long))
size = ULONG_MAX;
else if (bytes == sizeof(unsigned long long))
size = ULLONG_MAX;

return 0;
}

Can this code give the maximum value of size_t in all standard C
compliant compilers.

No, because there is no guarantee that size_t has the same size as any
other integer type. But you can do this:

#include <stddef.h>

int main(void)
{
size_t size = (size_t)-1;
return 0;
}
 
S

subramanian100in

(size_t) - 1

Please let me know whether this will give the maximum value of size_t
 
R

Richard Heathfield

(e-mail address removed), India said:
(size_t) - 1

Please let me know whether this will give the maximum value of size_t

Didn't I just do that? Yes, it will.
 
S

subramanian100in

Yes. It does give the expected value. Thanks.

The following is a beginner's question.

What is (size_t) ? ie what is parenthesized size_t ? how does it
produce a value ?

Please explain
 
C

Chris Dollin

Yes. It does give the expected value. Thanks.

The following is a beginner's question.

What is (size_t) ? ie what is parenthesized size_t ?

Your C book should tell you. (If you haven't got one, get
one; you'll make progress faster than by being drip-fed via
netnews. See the FAQ for suggestions.)

It's a type-name in brackets.

In the expression `(size_t) -1`, it's a /cast/, requesting
a conversion of the expression `-1` to the type `size_t`.

[Note that `-1` is an expression, not a literal, consisting
of the unary minus operator applied to the literal `1`.
It happens to be a /constant expression/, meaning that the
compiler can -- and in some circumstances [1], must -- evaluate
it at compile-time.]
how does it produce a value ?

It converts the value -1 to the guaranteed-unsigned type
`size_t` by adding/subtracting one more than the maximum
value of that type: ie taking it modulo maxvalue+1.

[1] eg as a case label.
 
S

shadowman

Yes. It does give the expected value. Thanks.

The following is a beginner's question.

What is (size_t) ? ie what is parenthesized size_t ? how does it
produce a value ?

Please explain

It's a typecast. In this case it's converting the value -1 to the type
size_t -- which is unsigned.
 
S

shadowman

Richard said:
shadowman said:


Well, close. It's a cast. C doesn't have anything called "typecast".

I must have been thinking about actors who always play similar roles.
 
S

santosh

(size_t) - 1

Please let me know whether this will give the maximum value of size_t

Please quote context.

Yes it will, not only for size_t, but for any unsigned type, (with the
appropriate cast).

You can also use the SIZE_MAX macro defined in stdint.h, to get the
maximum value of the system's size_t type. It's however a C99 feature.
 
J

John Bode

Yes. It does give the expected value. Thanks.

The following is a beginner's question.

What is (size_t) ? ie what is parenthesized size_t ? how does it
produce a value ?

Please explain

Assume the statement

size_t size = (size_t) -1;

Starting from the right, the expression '1' is a constant integer
expression, its type is int, and its value is 1. We then apply the
unary negation operator '-' to that expression to get the integer type
value -1.

The expression '(size_t)' is a cast; it's purpose is to convert the
type of the signed integer value -1 to size_t, which is an unsigned
type. When a value falls outside of an unsigned type's range, it
"wraps" to a value within the range that's congruent to the original
value modulo 2^n, where n is the number of bits in the type.

For example, assume an unsigned type with 2 bits; it can store the
values 0, 1, 2, and 3. If we try to store a value that falls outside
of that range, the result will be mapped to the range [0,3]:

Actual value Stored value
------------ ------------
0 0
1 1
2 2
3 3
4 0
5 1
6 2
7 3
8 0
-1 3
-2 2
-3 1
-4 0
-5 3
-6 2
-7 1
-8 0

So, for our imaginary 2-bit unsigned type, the signed integer value -1
maps to the unsigned value 3.

A similar thing happens for converting the signed integer value -1 to
size_t; the resulting value will be the largest value that can be
represented in size_t.
 
S

spacecriter \(Bill C\)

Richard said:
(e-mail address removed), India said:


No, because there is no guarantee that size_t has the same size as any
other integer type. But you can do this:

#include <stddef.h>

int main(void)
{
size_t size = (size_t)-1;
return 0;
}

This appears to work on a 2's compliment machine.

Does it also work on a machine uses sign-magnitude numeric representations?
 
B

Ben Pfaff

spacecriter \(Bill C\) said:
Richard Heathfield wrote: [equivalent to SIZE_MAX]
size_t size = (size_t)-1;

This appears to work on a 2's compliment machine.

Does it also work on a machine uses sign-magnitude numeric representations?

Yes. The rule for conversion of negative integer value to
a unsigned integer type is to add <type>_MAX+1. It doesn't
depend on the numeric representation.
 
K

Keith Thompson

Richard Heathfield said:
(e-mail address removed), India said:

The code in the original article was indented; the indentation was
lost in Richard's followup, at least as I saw it. Probably something
somewhere doesn't like tab characters. Try to use only spaces for
indentation when posting to Usenet. (I've maually re-indented the
code here.)
No, because there is no guarantee that size_t has the same size as any
other integer type. But you can do this:

#include <stddef.h>

int main(void)
{
size_t size = (size_t)-1;
return 0;
}

You're right, of coures, that (size_t)-1 is a better solution than the
if/else chain above. A quibble, however: size_t *is* guaranteed to
have the same size as some other integer type. It's a typedef, and it
has to be an alias for something. In C99, however, it could be an
alias for an extended integer type rather than for one of the standard
predefined integer types. (I suppose a C90 implementation could
provide such types as an extension.)

In C90, the type "unsigned long long" doesn't exist (though it's a
common extension). You can either drop "unsigned long long" and have
the code break on implementations where unsigned long long is bigger
than unsigned long and size_t is an alias for unsigned long long, *or*
you can include it and have the code break on systems that don't
support unsigned long long. The __STDC_VERSION__ macro should tell
you what version of C is supported, but there are plenty of
implementations that support unsigned long long without supporting all
of C99.

Implementations are encouraged *not* to make size_t bigger than
unsigned long long unless it's actually necessary. (This is in n1124,
but not in the original C99 standard.) But this doesn't do you much
good.

It's conceivable, though vanishingly unlikely, that size_t is an alias
for unsigned short, or even unsigned char. Perhaps the DS9K does
this.

It's also possible for unsigned int and unsigned long to have the same
size, but for unsigned long to have a wider range (if unsigned int has
padding bits). If size_t on such a system is an alias for unsigned
long, then the above code will quietly produce an incorrect result.

In C99, <stdint.h> defines the SIZE_MAX macro, which is exactly what
you're looking for, but not all implementations provide it.
 
R

Richard Heathfield

Keith Thompson said:

You're right, of coures, that (size_t)-1 is a better solution than the
if/else chain above. A quibble, however: size_t *is* guaranteed to
have the same size as some other integer type.

Sorry, you're right - I should have said that it is not guaranteed to
have the same size as any other *standard* integer type. For example:

typedef _size_type size_t;

is one legal way for an implementation to "declare" size_t, where
_size_type might be a 24-bit type in, say, a C8SI16LP32 system.
 
Y

Yevgen Muntyan

Keith said:
Richard Heathfield said:
(e-mail address removed), India said: [snip]
Can this code give the maximum value of size_t in all standard C
compliant compilers.
No, because there is no guarantee that size_t has the same size as any
other integer type. But you can do this:

#include <stddef.h>

int main(void)
{
size_t size = (size_t)-1;
return 0;
}
[snip]
Implementations are encouraged *not* to make size_t bigger than
unsigned long long unless it's actually necessary. (This is in n1124,
but not in the original C99 standard.) But this doesn't do you much
good.

Isn't that even just unsigned long?

================
The types used for size_t and ptrdiff_t should not have an integer
conversion rank greater than that of signed long int unless the
implementation supports objects large enough to make this necessary.
================

Does the above imply that size_t should be a type with sizeof() <
sizeof(long)? ("integer conversion rank greater than that of signed
long int" doesn't sound quite clear)

It indeed doesn't do much good since MS ignores C99 and has long
smaller than size_t in its fancy 64-bit implementation.

Thanks,
Yevgen
 
S

spacecriter \(Bill C\)

Ben said:
spacecriter \(Bill C\) said:
Richard Heathfield wrote: [equivalent to SIZE_MAX]
size_t size = (size_t)-1;

This appears to work on a 2's compliment machine.

Does it also work on a machine uses sign-magnitude numeric
representations?

Yes. The rule for conversion of negative integer value to
a unsigned integer type is to add <type>_MAX+1. It doesn't
depend on the numeric representation.

Cool.

Thanks!
 
K

Keith Thompson

Yevgen Muntyan said:
Keith said:
Richard Heathfield said:
(e-mail address removed), India said: [snip]
Can this code give the maximum value of size_t in all standard C
compliant compilers.
No, because there is no guarantee that size_t has the same size as
any other integer type. But you can do this:

#include <stddef.h>

int main(void)
{
size_t size = (size_t)-1;
return 0;
}
[snip]
Implementations are encouraged *not* to make size_t bigger than
unsigned long long unless it's actually necessary. (This is in n1124,
but not in the original C99 standard.) But this doesn't do you much
good.

Isn't that even just unsigned long?

Oops, yes, you're right. (I knew what I *meant* to write!)

[...]
Does the above imply that size_t should be a type with sizeof() <
sizeof(long)? ("integer conversion rank greater than that of signed
long int" doesn't sound quite clear)

Normally, for an implementation that follows the recommendation,
sizeof(size_t) <= sizeof(long). But integer conversion rank isn't
defined in terms of size. It's defined in terms of relationships
between specific types, and the standard elsewhere mandates certain
relationships between the *ranges*, not the sizes, of those types.
(The distinction only matters if some types have padding bits; on most
real-world implementations, they don't.)

Integer conversion rank is defined in C99 6.3.1.1. Briefly (and
incompletely):

Distinct types have distinct ranks even if they have the same
width (e.g., if int and long are both 32 bits, long still has
a greater rank than int).

Corresponding signed and unsigned types have the same rank.

long long > long > int > short > signed char

There are additional rules covering _Bool, enumerated types, and
extended integer types, and requiring consistency.
It indeed doesn't do much good since MS ignores C99 and has long
smaller than size_t in its fancy 64-bit implementation.

Yes, even a conforming C99 implementation is allowed to do that.
Apparently MS decided that keeping long at 32 bits was more important
than other considerations. I'd like to see a type system that didn't
require such ugly tradeoffs, but a language with such a system
couldn't reasonably be called C.
 
S

subramanian100in

------------------------
Please quote context. ------------------------

Yes it will, not only for size_t, but for any unsigned type, (with the
appropriate cast).

You can also use the SIZE_MAX macro defined in stdint.h, to get the
maximum value of the system's size_t type. It's however a C99 feature.

You have mentioned "Please quote context". WHat is meant by quoting
context? I do not understand this. Kindly explain.


Now I have a question on SIZE_MAX.

In the ISO C99 statndard document

www.open-std.org.jtc1.sc22.wg14.www.docs.n1124.pdf

in 7.18.3 in page 259
SIZE_MAX is mentioned as 65535

which is (2 raised to the power 16) - 1. Am I right ? But in Redhat
Enterprise Linux gcc implementation, in <stdint.h>, SIZE_MAX value is
defined as 4294967295 which is (2 raised to the power 32) - 1, I
think. I cannot understand this difference. Where am I going wrong.
Please explain
 
K

Keith Thompson

You have mentioned "Please quote context". WHat is meant by quoting
context? I do not understand this. Kindly explain.

Read <http://cfaj.freeshell.org/google/>.

At one time, Google Groups had a bug that made it very easy to post
followups with no quoted text. That web page started as a complaint
about that bug, along with some suggestions for working around it.
The bug has since been fixed, but the page still has some good
information on the topic, along with some good links.

To summarize: Each followup should quote enough of the parent message
so that the followup makes sense on its own to someone who hasn't seen
the parent.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

size_t in inttypes.h 4
Adding adressing of IPv6 to program 1
usage of size_t 190
size_t, ssize_t and ptrdiff_t 56
Weird result from size_t 5
Max value of a variable 9
return -1 using size_t??? 44
size_t and ptr_diff_t 9

Members online

No members online now.

Forum statistics

Threads
473,954
Messages
2,570,116
Members
46,704
Latest member
BernadineF

Latest Threads

Top