size_t range

X

Xenos

Is there a standard way to determine the max. value of size_t as a
compile-time constant? Will:

#define SIZE_T_MAX ((size_t) -1)

work in all cases, or just on 2s comp. machines?


DrX
 
J

Jeremy Yallop

Xenos said:
Is there a standard way to determine the max. value of size_t as a
compile-time constant? Will:

#define SIZE_T_MAX ((size_t) -1)

work in all cases, or just on 2s comp. machines?

It will work in all cases. Casts work on values, not representations.
For what it's worth, C99 defines a SIZE_MAX macro whose value is the
maximum value of size_t.

Jeremy.
 
P

Peter Pichler

Xenos said:
Is there a standard way to determine the max. value of size_t as a
compile-time constant? Will:

#define SIZE_T_MAX ((size_t) -1)

work in all cases, or just on 2s comp. machines?

That's how I understand it. -1, converted to an unsigned type, gives
the maximum value for that type regardless of representation.

Peter
 
B

Barry Schwarz

Is there a standard way to determine the max. value of size_t as a
compile-time constant? Will:

#define SIZE_T_MAX ((size_t) -1)

work in all cases, or just on 2s comp. machines?


DrX
size_t is a typdef for some unsigned integer type. While ((size_t)-1)
will produce the max value that can be stored in that type, there is
no guarantee that any function or operator returning a size_t will
ever produce a value that large. The system is free to limit the
value of a size_t to a lesser value as long as it satisfies the
definition in the standard.

So the return question is do you mean the max value that will fit in a
size_t variable or the largest size of any object per the definition?


<<Remove the del for email>>
 
D

Dan Pop

In said:
size_t is a typdef for some unsigned integer type. While ((size_t)-1)
will produce the max value that can be stored in that type, there is
no guarantee that any function or operator returning a size_t will
ever produce a value that large. The system is free to limit the
value of a size_t to a lesser value as long as it satisfies the
definition in the standard.

So the return question is do you mean the max value that will fit in a
size_t variable or the largest size of any object per the definition?

The largest size of any object doesn't make much sense, except on
single user, single tasking platforms, as it can change during the
program's execution, due to other activity on the same system. And the
systems where it makes sense, usually provide it, via an extension.

What really matters is not to exceed (size_t)-1 in an argument to a
function expecting a size_t parameter, because this leads to programming
errors. Consider malloc(100000) on a system with (size_t)-1 == 65535.
The call may succeed, but it won't allocate the expected amount of memory.

Dan
 
L

Leon

The largest size of any object doesn't make much sense, except on
single user, single tasking platforms, as it can change during the
program's execution, due to other activity on the same system. And the
systems where it makes sense, usually provide it, via an extension.

What really matters is not to exceed (size_t)-1 in an argument to a
function expecting a size_t parameter, because this leads to programming
errors. Consider malloc(100000) on a system with (size_t)-1 == 65535.
The call may succeed, but it won't allocate the expected amount of memory.

Dan


I tried this macro on gcc and on Microsoft Visual Studio C compiler,
the result of (size_t) -1 is still -1. The size_t is typedef as
unsigned int.

However, result of (unsigned char)-1, (unsigned short)-1 are both
correct.

Only (unsigned int) -1 still returns -1. Why is that?

Thanks.
 
C

Christian Bau

I tried this macro on gcc and on Microsoft Visual Studio C compiler,
the result of (size_t) -1 is still -1. The size_t is typedef as
unsigned int.

However, result of (unsigned char)-1, (unsigned short)-1 are both
correct.

Only (unsigned int) -1 still returns -1. Why is that?

How exactly did you figure out that "the result of (size_t) -1 is still
-1" ? I assure you that it is not; for starters, the types of both
expressions are different; one is of type size_t, the other is of type
int.
 
P

pete

Christian said:
How exactly did you figure out that
"the result of (size_t) -1 is still -1" ?

According to my crystal ball, he used the expression,
((size_t)-1 == -1)
I assure you that it is not; for starters, the types of both
expressions are different; one is of type size_t, the other is of type
int.

.... and he didn't realise that the -1 int value,
was getting converted to UINT_MAX.
 
C

CBFalconer

Leon said:
.... snip ...

I tried this macro on gcc and on Microsoft Visual Studio C
compiler, the result of (size_t) -1 is still -1. The size_t is
typedef as unsigned int.

However, result of (unsigned char)-1, (unsigned short)-1 are
both correct.

Only (unsigned int) -1 still returns -1. Why is that?

How did you show that result?
 
L

Leon

pete said:
According to my crystal ball, he used the expression,
((size_t)-1 == -1)


... and he didn't realise that the -1 int value,
was getting converted to UINT_MAX.

Here is what I did,

#include <stdio.h>
#define SIZE_T_MAX ((size_t) -1)
#define UCHAR_MAX ((unsigned char) -1)
#define USHORT_MAX ((unsigned short) -1)
#define UINT_MAX ((unsigned int) -1)

int main()
{

printf("SIZE_T_MAX %d\n", SIZE_T_MAX);
printf("UCHAR_MAX %d\n", UCHAR_MAX);
printf("USHORT_MAX %d\n", USHORT_MAX);
printf("UINT_MAX %d\n", UINT_MAX);
}

and thet result is :

SIZE_T_MAX -1
UCHAR_MAX 255
USHORT_MAX 65535
UINT_MAX -1

I know that (char)-1 is represented as 0xFF as two's complement. so it
doesn't surprise me that (unsigned char)-1 is 255. However, shouldn't
(int)-1 be represented as 0xFFFFFFFF in and thus have a unsigned value
of 2^32 - 1? Basically,I don;t understand why SIZE_T_MAX and UINT_MAX
evaluates to -1.

can you explain the result of my code? Thanks a lot!
 
M

Martin Ambuhl

Leon said:
I tried this macro on gcc and on Microsoft Visual Studio C compiler,
the result of (size_t) -1 is still -1. The size_t is typedef as
unsigned int.

How do you know this? gcc, for example, uses unsigned long for size_t.
And unsigned variables are never -1.
 
M

Martin Ambuhl

Leon said:
Here is what I did,

#include <stdio.h>
#define SIZE_T_MAX ((size_t) -1)
#define UCHAR_MAX ((unsigned char) -1)
#define USHORT_MAX ((unsigned short) -1)
#define UINT_MAX ((unsigned int) -1)

int main()
{

printf("SIZE_T_MAX %d\n", SIZE_T_MAX);
printf("UCHAR_MAX %d\n", UCHAR_MAX);
printf("USHORT_MAX %d\n", USHORT_MAX);
printf("UINT_MAX %d\n", UINT_MAX);

The specifier for an unsigned value is "%u", not "%d" (and for a long
unsigned is "%lu"). You told printf to interpret the argument as
signed, and it did. Do you also use "%d" to print floating values and
then complain that they're not right?
 
C

Christian Bau

Here is what I did,

#include <stdio.h>
#define SIZE_T_MAX ((size_t) -1)
#define UCHAR_MAX ((unsigned char) -1)
#define USHORT_MAX ((unsigned short) -1)
#define UINT_MAX ((unsigned int) -1)

int main()
{

printf("SIZE_T_MAX %d\n", SIZE_T_MAX);
printf("UCHAR_MAX %d\n", UCHAR_MAX);
printf("USHORT_MAX %d\n", USHORT_MAX);
printf("UINT_MAX %d\n", UINT_MAX);
}

%d is used to print values of type int. %d will print the correct values
in the following cases:

1. If the argument is of type int.
2. If the argument is of type char or short, because it will be
promoted to type int.
3. If the argument is of type unsigned char, unsigned short, or
unsigned int, and it is small enough to fit into an int.

On most implementations, unsigned char has less bits than int, so case
(3) applies and (unsigned char) -1 is printed correctly. Use %u instead.

On many implementations, unsigned short has fewer bits than int, so case
(3) applies and (unsigned short) -1 is printed correctly. Won't work on
a 16 bit DOS compiler. Use %u instead.

(unsigned int) -1 is practically guaranteed not to give the correct
result. Use %u instead.

(size_t) -1 is even more guaranteed no to work. size_t can have more
bits than int, and then you are in real trouble. Using %d to print a
value of type size_t is a serious bug in your program.
 
K

Keith Thompson

Here is what I did,

#include <stdio.h>
#define SIZE_T_MAX ((size_t) -1)
#define UCHAR_MAX ((unsigned char) -1)
#define USHORT_MAX ((unsigned short) -1)
#define UINT_MAX ((unsigned int) -1)

int main()
{

printf("SIZE_T_MAX %d\n", SIZE_T_MAX);
printf("UCHAR_MAX %d\n", UCHAR_MAX);
printf("USHORT_MAX %d\n", USHORT_MAX);
printf("UINT_MAX %d\n", UINT_MAX);
}

The "%d" format expects a signed int argument. In the first call
you're passing an unsigned value and telling printf that it's a signed
value. If you lie to printf, it will probably lie to you.

The printf function has know way of knowing the types of the arguments
you pass it; the only information it has is is the format string.
Getting the types right is entirely the caller's responsibility.

Try this instead:

#include <stdio.h>
#define MY_SIZE_T_MAX ((size_t) -1)
#define MY_UCHAR_MAX ((unsigned char) -1)
#define MY_USHORT_MAX ((unsigned short) -1)
#define MY_UINT_MAX ((unsigned int) -1)

int main()
{
printf("MY_SIZE_T_MAX %lu\n", (unsigned long)MY_SIZE_T_MAX);
printf("MY_UCHAR_MAX %u\n", (unsigned)MY_UCHAR_MAX);
printf("MY_USHORT_MAX %u\n", (unsigned)MY_USHORT_MAX);
printf("MY_UINT_MAX %u\n", MY_UINT_MAX);
return 0;
}

I prefixed all the macros with "MY_", since some of them conflict with
names in <limits.h> (which you didn't #include, but it's best to avoid
re-declaring identifiers declared in standard headers).

I cast MY_SIZE_T_MAX to unsigned long (since it may be bigger than
unsigned int on some platforms), and used the appropriate format.
MY_UCHAR_MAX and MY_USHORT_MAX are guaranteed to fit in an unsigned
int, so I used that rather than unsigned long, and of course
MY_UINT_MAX is already an unsigned int.

On one system, the revised program gave me the following output (other
systems may vary):

MY_SIZE_T_MAX 4294967295
MY_UCHAR_MAX 255
MY_USHORT_MAX 65535
MY_UINT_MAX 4294967295
 
K

Keith Thompson

Keith Thompson said:
The printf function has know way of knowing the types of the arguments
you pass it; the only information it has is is the format string.
Getting the types right is entirely the caller's responsibility.
[...]

Argh. I should proofread before I post. Of course I meant,
"The printf function has know way of noing ...".

Or something like that.
 
D

Dan Pop

In said:
Here is what I did,

#include <stdio.h>
#define SIZE_T_MAX ((size_t) -1)
#define UCHAR_MAX ((unsigned char) -1)
#define USHORT_MAX ((unsigned short) -1)
#define UINT_MAX ((unsigned int) -1)

int main()
{

printf("SIZE_T_MAX %d\n", SIZE_T_MAX);
printf("UCHAR_MAX %d\n", UCHAR_MAX);
printf("USHORT_MAX %d\n", USHORT_MAX);
printf("UINT_MAX %d\n", UINT_MAX);
}

I could have sworn that this is what you did, when I read your first post.
Never ever use a library function again before *carefully* reading its
specification.

UCHAR_MAX and USHORT_MAX are likely to get promoted to int, so %d is the
right thing and you get the expected results. Beware of 8 and 16-bit
compilers, where USHORT_MAX is going to be promoted to unsigned int,
though... So, to be on the safe side, convert USHORT_MAX to unsigned int
yourself and display it using %u instead of %d.

UINT_MAX will never be converted to int in this context and it is
highly unlikely that SIZE_T_MAX will.

For UINT_MAX, the solution is %u, since this is the correct conversion
descriptor for an unsigned int.

For SIZE_T_MAX things are a bit more complicated, because you don't
know its type and C89 doesn't provide any conversion descriptor that
is guaranteed to be the right thing for size_t. So, the C89 solution
is to use %lu and convert SIZE_T_MAX to unsigned long (the largest
unsigned type supported by the language). In C99, you can use the %zu
conversion descriptor for size_t values.

So, try:

printf("UINT_MAX %u\n", UINT_MAX);
printf("SIZE_T_MAX %lu\n", (unsigned long)SIZE_T_MAX);

and I bet you won't see any -1 nonsense!

Dan
 

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

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,528
Members
45,000
Latest member
MurrayKeync

Latest Threads

Top