How to use maximum size of size_t type ?

Discussion in 'C Programming' started by javadesigner, Jan 21, 2004.

  1. javadesigner

    javadesigner Guest

    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
     
    javadesigner, Jan 21, 2004
    #1
    1. Advertising

  2. javadesigner

    pete Guest

    javadesigner wrote:
    >
    > 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.

    --
    pete
     
    pete, Jan 21, 2004
    #2
    1. Advertising

  3. Greetings.

    In article <bulvs5$bikj$>, javadesigner wrote:
    > 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

    --
    _
    _V.-o Tristan Miller [en,(fr,de,ia)] >< Space is limited
    / |`-' -=-=-=-=-=-=-=-=-=-=-=-=-=-=-= <> In a haiku, so it's hard
    (7_\\ http://www.nothingisreal.com/ >< To finish what you
     
    Tristan Miller, Jan 21, 2004
    #3
  4. javadesigner

    Richard Bos Guest

    javadesigner <> wrote:

    > 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
    #include <stdlib.h>. malloc() returns a void *, which is useful exactly
    because it can hold all kinds of pointers and doesn't need casts.

    > 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
     
    Richard Bos, Jan 21, 2004
    #4
  5. javadesigner

    Dan Pop Guest

    In <> (Richard Bos) writes:

    >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
    --
    Dan Pop
    DESY Zeuthen, RZ group
    Email:
     
    Dan Pop, Jan 21, 2004
    #5
  6. javadesigner

    javadesigner Guest

    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
     
    javadesigner, Jan 22, 2004
    #6
  7. 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.

    --
    a signature
     
    those who know me have no need of my name, Jan 22, 2004
    #7
  8. javadesigner

    pete Guest

    javadesigner wrote:
    >
    > 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.

    --
    pete
     
    pete, Jan 22, 2004
    #8
  9. javadesigner

    javadesigner Guest

    > 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
     
    javadesigner, Jan 22, 2004
    #9
  10. javadesigner

    pete Guest

    javadesigner wrote:
    >
    > > 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 ?


    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.

    --
    pete
     
    pete, Jan 22, 2004
    #10
  11. javadesigner

    pete Guest

    pete wrote:

    > 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).

    --
    pete
     
    pete, Jan 22, 2004
    #11
  12. javadesigner

    Dan Pop Guest

    In <> those who know me have no need of my name <> writes:

    >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
    --
    Dan Pop
    DESY Zeuthen, RZ group
    Email:
     
    Dan Pop, Jan 22, 2004
    #12
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Dave
    Replies:
    1
    Views:
    485
    David B. Held
    Oct 20, 2003
  2. Alex Vinokur
    Replies:
    9
    Views:
    833
    James Kanze
    Oct 13, 2008
  3. Alex Vinokur
    Replies:
    1
    Views:
    612
  4. phanhuyich
    Replies:
    4
    Views:
    332
  5. James Harris
    Replies:
    12
    Views:
    338
    Malcolm McLean
    Oct 9, 2013
Loading...

Share This Page