How to use maximum size of size_t type ?

J

javadesigner

Hi:

I am a bit new to C programming and am trying to
write a wrapper around malloc. Since malloc takes
size_t as it's parameter, I want to be able to
see if my function recieved an argument less than
or equal to the max size_t type.

So:

//my wrapper function mallocstr
char * mallocstr(size_t num)
{
//TEST
if (CODE HERE TO TEST FOR num <= max size of size_t) {
printf("some debug error message\n");
return NULL;
}
//END TEST
return (char *) malloc(num);
}


Now, ignore the fact that malloc will return NULL if
unsucessful and I may not need the test. If I _do_
want to structure my code in the above fashion, is there
any _way_ to do it ?

I.E., replace the "CODE HERE..." line with some
test that can tell me with my argument was less than
of equal to the max size of the size_t type.

I am on a gcc system and would like to do this portably.
As far as I can tell, there is no gcc defined macro
or any value in limit.h that tells me the max size of
size_t.

Maybe I am missing something, but this appears tougher
than it should be.

Best regards,

--j
 
P

pete

javadesigner said:
Hi:

I am a bit new to C programming and am trying to
write a wrapper around malloc. Since malloc takes
size_t as it's parameter, I want to be able to
see if my function recieved an argument less than
or equal to the max size_t type.

So:

//my wrapper function mallocstr
char * mallocstr(size_t num)
{
//TEST
if (CODE HERE TO TEST FOR num <= max size of size_t) {
printf("some debug error message\n");
return NULL;
}
//END TEST
return (char *) malloc(num);
}

Now, ignore the fact that malloc will return NULL if
unsucessful and I may not need the test. If I _do_
want to structure my code in the above fashion, is there
any _way_ to do it ?

I.E., replace the "CODE HERE..." line with some
test that can tell me with my argument was less than
of equal to the max size of the size_t type.

I am on a gcc system and would like to do this portably.
As far as I can tell, there is no gcc defined macro
or any value in limit.h that tells me the max size of
size_t.

Maybe I am missing something, but this appears tougher
than it should be.

It's pointless.
Any value that you can test within the function,
will be within the range of size_t.
The largest value that will fit in a size_t object,
is ((size_t)-1).

There's a SIZE_MAX macro in C99.
 
T

Tristan Miller

Greetings.

I am on a gcc system and would like to do this portably.
As far as I can tell, there is no gcc defined macro
or any value in limit.h that tells me the max size of
size_t.

Maybe I am missing something, but this appears tougher
than it should be.

C99 (and possibly earlier standards; I don't remember) define the SIZE_MAX
macro. It's supported by recent versions of GCC.

A portable fallback is to use the expression (size_t)(-1).

Regards,
Tristan
 
R

Richard Bos

javadesigner said:
I am a bit new to C programming and am trying to
write a wrapper around malloc. Since malloc takes
size_t as it's parameter, I want to be able to
see if my function recieved an argument less than
or equal to the max size_t type.

Erm. If your function takes a size_t argument...
//my wrapper function mallocstr
char * mallocstr(size_t num)

....which it does, then there's no way you're ever going to get an
argument that does _not_ fit in a size_t. Even if someone tries to pass
a larger number to your function, it's going to be modulated down to
size before being passed to mallocstr(). If size_t could be signed, too
large arguments would invoke I-DB, but it's required to be unsigned, so
it is always going to be passed to you modulo SIZE_MAX.
return (char *) malloc(num);

There is no reason to cast malloc(), btw, unless you have forgotten to
Now, ignore the fact that malloc will return NULL if
unsucessful and I may not need the test. If I _do_
want to structure my code in the above fashion, is there
any _way_ to do it ?

Partially. Instead of a size_t, take a uintmax_t and check whether your
parameter is <=SIZE_MAX. Since neither of those exists in C89, you'll
have to make do with unsigned long ans (size_t)-1 if you don't have C99.
This means your function doesn't take the same kind of argument as
malloc(), however.
Moreover, size_t could even be larger than unsigned long (at least, I
can't find a reason why it couldn't), which would mean that mallocstr()
would actually have a smaller range than malloc(). In C99, with
uintmax_t, that would not be a problem.
As far as I can tell, there is no gcc defined macro
or any value in limit.h that tells me the max size of
size_t.

Not if you have a pre-C99 version of gcc, but since size_t is guaranteed
to be unsigned and values assigned to unsigned types are changed modulo
the size of the type if they're out of range, (size_t)-1 will give you
the maximum value of a size_t. It's still not much use if you take a
size_t in the first place, of course.

Richard
 
D

Dan Pop

In said:
Moreover, size_t could even be larger than unsigned long (at least, I
can't find a reason why it couldn't), which would mean that mallocstr()
would actually have a smaller range than malloc().

Nope, this is not possible in C89, which doesn't have extended integer
types. A conforming C89 implementation may define __longlong as an
extension, but it doesn't count as an integer type from C89's point of
view.

Dan
 
J

javadesigner

Hi:

Firstly, thanks to all who replied. I am amazed
at the high signal/noise ratio in this group (unlike
other comp.lang.* groups).

So the whole idea of mallocstr was to make sure
my string allocation had the "1 more" char for
the null (\0) terminator. I know I'll forget to
mallon (len + 1) so why not have a mallocstr
that does that for me automatically ?

I reason, I needed to check to see if the supplied
argument was len < max size of size_t was to ensure
enough space for len + 1

So

#define DBG_FLOW 1

#define pfcall(argstr, args) \
printf("--> %s(" argstr ") [%s, %d]\n", __func__, (args), __FILE__,
__LINE__)

#define fpfcall(fd, argstr, args) \
fprintf(fd, "%s(" argstr ") [%s, %d]\n", __func__, (args), __FILE__,
__LINE__)

typedef char * string; //personal preference

string mallocstr(size_t num_chars)
{
#ifdef DBG_FLOW
pfcall("%zu", num_chars);
#endif;

if (num_chars == (size_t) -1) //or num_chars == SIZE_MAX
{
fpfcall(stderr,
"Cannot allocate chars since %zu == max size_t and no space left for one
more \\n character\n",
num_chars);
return NULL;
}
return (string) malloc(num_chars + 1);
}

Comments ? Again, I am new to C so please _do_ flame me
if the above code/debug macros suck.

Best regards,

--j
 
T

those who know me have no need of my name

in comp.lang.c i read:
there's no way you're ever going to get an argument that does _not_ fit in
a size_t. Even if someone tries to pass a larger number to your function,
it's going to be [...] modulo SIZE_MAX.

only if SIZE_MAX is the same as the maximum value of the underlying
unsigned type. that is almost certain to be the case except in a
pathological implementation, e.g., where size_t is an alias for unsigned
long and ULONG_MAX is 4294967295 but SIZE_MAX is 2147483647.
Moreover, size_t could even be larger than unsigned long (at least, I
can't find a reason why it couldn't),

size_t must be an alias for an unsigned integral type, and pre-c99 there
are no extended types so at most it's an unsigned long in those compilers.
 
P

pete

javadesigner said:
Hi:

Firstly, thanks to all who replied. I am amazed
at the high signal/noise ratio in this group (unlike
other comp.lang.* groups).

So the whole idea of mallocstr was to make sure
my string allocation had the "1 more" char for
the null (\0) terminator. I know I'll forget to
mallon (len + 1) so why not have a mallocstr
that does that for me automatically ?

I reason, I needed to check to see if the supplied
argument was len < max size of size_t was to ensure
enough space for len + 1

So

#define DBG_FLOW 1

#define pfcall(argstr, args) \
printf("--> %s(" argstr ") [%s, %d]\n", __func__, (args), __FILE__,
__LINE__)

#define fpfcall(fd, argstr, args) \
fprintf(fd, "%s(" argstr ") [%s, %d]\n", __func__, (args), __FILE__,
__LINE__)

typedef char * string; //personal preference

string mallocstr(size_t num_chars)
{
#ifdef DBG_FLOW
pfcall("%zu", num_chars);
#endif;

if (num_chars == (size_t) -1) //or num_chars == SIZE_MAX
{
fpfcall(stderr,
"Cannot allocate chars since %zu == max size_t and no space left for one
more \\n character\n",
num_chars);
return NULL;
}
return (string) malloc(num_chars + 1);
}

Comments ? Again, I am new to C so please _do_ flame me
if the above code/debug macros suck.

The only way I can imagine that a string's null terminating
character could be more that ((size_t)-1) away from
the head of the string,
is if the string spans at least two different objects.
As far as I know, string spanning across two unrelated objects,
is merely an accidental condition that can be checked for,
rather than something that you can code deliberately.

If your string is contained within an object, like every
useful string in real code is, then size_t is big enough.
 
J

javadesigner

The only way I can imagine that a string's null terminating
character could be more that ((size_t)-1) away from
the head of the string,
is if the string spans at least two different objects.

As a newbie, I have no idea what you mean by "object". I am
presuming you don't mean C++ objects of course, so what does
'object' refer to in the context of plain old C ?

Best regards,

--j
 
P

pete

javadesigner said:
As a newbie, I have no idea what you mean by "object". I am
presuming you don't mean C++ objects of course, so what does
'object' refer to in the context of plain old C ?

All variables are objects. Function parameters are objects.
When a string literal "like this one" is used to initialize
a string pointer, the string literal is paradoxically, the
name of an anonymous object, that object being an array of char.
Multiple occurances of identical string literals in code,
may refer to the same object, or may each refer to a different one.

* Object --- a region of data storage in the execution environment,
the contents of which can represent values. Except for bit-fields,
objects are composed of contiguous sequences of one or more bytes,
the number, order, and encoding of which are either explicitly
specified or implementation-defined.
 
P

pete

pete said:
When a string literal "like this one" is used to initialize
a string pointer, the string literal is paradoxically, the
name of an anonymous object, that object being an array of char.

When a string literal "like this one" is used to initialize
an array of char, then it is just an initializer list and doesn't
imply that there is any other array besides the one being initialized.

When it is the operand of sizeof, it's an array.
sizeof"this" equals 5, (4 characters plus 1 more null character).
 
D

Dan Pop

In said:
in comp.lang.c i read:
there's no way you're ever going to get an argument that does _not_ fit in
a size_t. Even if someone tries to pass a larger number to your function,
it's going to be [...] modulo SIZE_MAX.

only if SIZE_MAX is the same as the maximum value of the underlying
unsigned type. that is almost certain to be the case except in a
pathological implementation, e.g., where size_t is an alias for unsigned
long and ULONG_MAX is 4294967295 but SIZE_MAX is 2147483647.

Such an implementation would be non-conforming. SIZE_MAX is a property
of the type aliased by size_t, so, if size_t is an alias for unsigned
long, SIZE_MAX *must* be the same as ULONG_MAX. There is no way to have
(size_t)-1 != SIZE_MAX in a conforming implementation.

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

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,815
Latest member
treekmostly22

Latest Threads

Top