printf() Specification for size_t?

Discussion in 'C Programming' started by David T. Ashley, Feb 21, 2008.

  1. What printf() format specifier will allow me to print a size_t integer?

    Seems like it should be there, but couldn't find it in documentation.

    I'm using %ul, but that might not work on every system, I think.

    Thanks.
     
    David T. Ashley, Feb 21, 2008
    #1
    1. Advertisements

  2. David T. Ashley

    dj3vande Guest

    For C90, cast it to unsigned long and use %lu:
    --------
    printf("The size_t value is %lu\n",(unsigned long)sz);
    --------
    If you have C99, use %zu.

    Note that %lu and %ul are not the same.


    dave
     
    dj3vande, Feb 21, 2008
    #2
    1. Advertisements

  3. Under C90, you should use the largest (portable)
    unsigned integer type, namely unsigned long...

    printf("%lu\n", (unsigned long) sizeof x);

    Under C99, you can use the length modifier z...

    printf("%zu\n", sizeof x);
    Which will print an unsigned int value followed by an
    ell.
    Using unsigned long (uncluding conversion) is reasonably
    forwards compatible. That said, it's possible to cater
    for both worlds with some conditional includes and macros,
    but it generally isn't worth the hassle since it's
    relatively rare to print a size_t without knowing limits
    on how big the object that it refers to can reasonably
    be.

    For instance, if you're dealing with objects that might
    be larger than 4G, then you're more likely to be printing
    the size in megabytes or gigabytes. Either way the integer
    calculation is likely to be in the range of an unsigned
    long.
     
    Peter Nilsson, Feb 21, 2008
    #3
  4. I had a brain malfunction. I actually used %lu, which worked fine, but
    somehow in the newsgroup post I stated "%ul".

    I'm aware that on my platform, "lu" works fine (naturally, I looked up the
    size_t definition before I did this).

    My only fear (and the reason I made the post) is that I could envision
    platforms where the largest integer has far more bits than the address space
    of the machine. I've never seen such a thing, but it seems it could exist.

    In other words, I can't figure out why size_t _____necessarily_____ has any
    relationship to the largest integer size.
     
    David T. Ashley, Feb 21, 2008
    #4
  5. I had a brain malfunction. I actually used %lu, which worked fine, but
    somehow in the newsgroup post I stated "%ul".

    I'm aware that on my platform, "lu" works fine (naturally, I looked up the
    size_t definition before I did this).

    My only fear (and the reason I made the post) is that I could envision
    platforms where the largest integer has far more bits than the address space
    of the machine. I've never seen such a thing, but it seems it could exist.

    In other words, I can't figure out why size_t _____necessarily_____ has any
    relationship to the largest integer size.
     
    David T. Ashley, Feb 21, 2008
    #5
  6. "%ul" should never work, while "%lu" often will.

    If you have a library supporting the C99 specifier "%zu", use that.
    Otherwise, you can't get much safer than
    "%llu" with a cast to (unsigned long long)
    If your implementation supports neither, then use
    "%lu" with a cast to (unsigned long)
    and pray.
     
    Martin Ambuhl, Feb 21, 2008
    #6
  7. Martin Ambuhl said:
    I see no reason why %ul should not work. There is nothing to stop
    implementors from using unsigned ints as the underlying type for size_t,
    and there is nothing to stop programmers from putting an 'l' onto stdout
    immediately after the size value.
     
    Richard Heathfield, Feb 21, 2008
    #7
  8. size_t is necessarily no bigger than the largest integer size.
    There's no guarantee that it's the same as any particular predefined
    integer type, which is why (unless you have "%zu") you have to convert
    it to some type to print it.

    In C90, the largest unsigned integer type (size_t is guaranteed to be
    an unsigned type) is unsigned long, so this:

    size_t size = <whatever>;
    printf("size = %lu\n", (unsigned long)size);

    should always work. In C99, unsigned long long isn't guaranteed to be
    the widest unsigned integer type (an implementation can provide
    extended integer types), and it's conceivable that size_t could be
    wider than unsigned long. It's guaranteed that size_t is no wider
    than uintmax_t, but since C99 provides formats for both size_t and
    uintmax_t that isn't all that helpful.

    If you need portability to both C90 and C99 implementations, you can
    still use the "%lu" trick *if* you can guarantee that the particular
    value you're printing is no greater than ULONG_MAX. Even if size_t is
    wider than unsigned long, if the value doesn't exceed ULONG_MAX then
    the cast performs a (narrowing) conversion that doesn't lose any
    information. (Even if the value is greater than ULONG_MAX, the
    semantics of unsigned types means that you'll just get an incorrect
    result; there's no undefined behavior.)

    If you know your code will run only under conforming C99
    implementations, you can use "%zu" (and there's no need for a cast).
    But note that, out in the real world, even testing for
    __STDC_VERSION__ >= 199901L doesn't necessarily guarantee that "%zu"
    will work. The __STDC_VERSION__ macro is set by the compiler; it's up
    to the runtime library to implement printf properly. An
    implementation combining a compiler and a runtime library *should* get
    this right, but I think that some don't.
     
    Keith Thompson, Feb 21, 2008
    #8
  9. Thank you for your valuable contribution.
     
    Martin Ambuhl, Feb 21, 2008
    #9
  10. Martin Ambuhl said:
    You're quite welcome, my dear chap!
     
    Richard Heathfield, Feb 21, 2008
    #10
  11. David T. Ashley

    CBFalconer Guest

    I think this will create great confusion for newbies. It should be
    labelled, etc. to attempt to avoid being taken too seriously.
     
    CBFalconer, Feb 21, 2008
    #11
  12. David T. Ashley

    vippstar Guest

    It would also confuse a newbie to think that %ul would print an
    unsigned long.
    When printf() encounters a % in the string literal, it searches for
    one of the conversion specifiers, which are
    d,i,a,u,x,X,f,F,e,E,g,G,a,A,c,s,p,n,%, and also parses any flag
    characters, length modifiers, precision and field width which are
    optional.
    When not doing that, printf() simply puts the bytes to stdout.
    So, according to that, %ul would be parsed as:
    %: start parsing
    u: valid conversion specifier. stop parsing
    l: byte. put (write) to stdout

    Hope this clears any confusion a newbie might had.

    Reference: 7.19.6.1 ISO C99
     
    vippstar, Feb 21, 2008
    #12
  13. Ouch! Twice the sarcasm cuts like a knife as we one again play "clc
    regulars eating their own"...
     
    Antoninus Twink, Feb 21, 2008
    #13
  14. David T. Ashley

    pete Guest

    That's why I call it (long unsigned) instead of (unsigned long).
     
    pete, Feb 21, 2008
    #14
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.