printf formats for size_t?

Discussion in 'C Programming' started by David Mathog, May 12, 2005.

  1. David Mathog

    David Mathog Guest

    size_t varies from system to system. This occasionally leads to
    coding issues such as:

    (void) sprintf(msg,"length of buffer: %d",strlen(msg));

    which worked fine on a 32 linux but triggered errors with gcc
    on an X86_64 system. (Ok, it should probably have been a %u rather
    than a %d, but since msg was always going to be short it didn't
    affect the program's execution.)

    The gcc printf man page indicates that "%zu", "%zx", etc. tell the
    compiler that the variable has type size_t, whatever size_t happens to
    be. Is "z" part of the C standard or is it a gcc extension? If the
    former, at what point did "z" become part of C?


    Thanks,

    David Mathog
     
    David Mathog, May 12, 2005
    #1
    1. Advertising

  2. David Mathog

    -berlin.de Guest

    David Mathog <> wrote:
    > size_t varies from system to system. This occasionally leads to
    > coding issues such as:


    > (void) sprintf(msg,"length of buffer: %d",strlen(msg));


    > which worked fine on a 32 linux but triggered errors with gcc
    > on an X86_64 system. (Ok, it should probably have been a %u rather
    > than a %d, but since msg was always going to be short it didn't
    > affect the program's execution.)


    Even better cast the size_t value to unsigned long and print with
    "%lu", so it works also if size_t is larger than int.

    > The gcc printf man page indicates that "%zu", "%zx", etc. tell the
    > compiler that the variable has type size_t, whatever size_t happens to
    > be. Is "z" part of the C standard or is it a gcc extension? If the
    > former, at what point did "z" become part of C?


    With the C99 standard. It says:

    'z' Specifies that a following 'd', 'i', 'o', 'u', 'x', or
    'X' conversion specifier applies to a 'size_t' or the
    corresponding signed integer type argument; or that a
    following 'n' conversion specifier applies to a pointer
    to a signed integer type corresponding to 'size'_t argu-
    ment.
    Regards, Jens
    --
    \ Jens Thoms Toerring ___ -berlin.de
    \__________________________ http://www.toerring.de
     
    -berlin.de, May 12, 2005
    #2
    1. Advertising

  3. David Mathog <> writes:
    > size_t varies from system to system. This occasionally leads to
    > coding issues such as:
    >
    > (void) sprintf(msg,"length of buffer: %d",strlen(msg));
    >
    > which worked fine on a 32 linux but triggered errors with gcc
    > on an X86_64 system. (Ok, it should probably have been a %u rather
    > than a %d, but since msg was always going to be short it didn't
    > affect the program's execution.)
    >
    > The gcc printf man page indicates that "%zu", "%zx", etc. tell the
    > compiler that the variable has type size_t, whatever size_t happens to
    > be. Is "z" part of the C standard or is it a gcc extension? If the
    > former, at what point did "z" become part of C?


    As Jens Toerring pointed out, the "%zu" format is new in C99. That
    means that some systems don't yet support it. (Incidentally, there is
    no "gcc printf man page". printf is part of the runtime library; gcc
    is just the compiler. gcc typically uses the native runtime library
    on a given system, so having a current version of gcc is no guarantee
    that printf() supports "%zu".)

    For C90, the best way to print a size_t value is to use "%lu" and cast
    the value to unsigned long. This will *almost* always work in C99 as
    well. The only case where it won't is when size_t is bigger than
    unsigned long (I don't know of any platforms where this is the case)
    *and* the specific value you're printing exceeds ULONG_MAX.

    For complete portability, you can query the __STDC_VERSION__ macro
    (first check whether it's defined, then check the value) to determine
    whether the implementation supports C99. On the other hand, just
    because the compiler defines __STDC_VERSION__ as 199901L, that doesn't
    necessarily guarantee that runtime library is also conforming. It
    should, and it's arguably a bug if it doesn't, but it's a bug I've
    seen on at least one real system.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, May 12, 2005
    #3
  4. David Mathog

    CBFalconer Guest

    -berlin.de wrote:
    > David Mathog <> wrote:
    >
    >> size_t varies from system to system. This occasionally leads to
    >> coding issues such as:

    >
    >> (void) sprintf(msg,"length of buffer: %d",strlen(msg));

    >
    >> which worked fine on a 32 linux but triggered errors with gcc
    >> on an X86_64 system. (Ok, it should probably have been a %u rather
    >> than a %d, but since msg was always going to be short it didn't
    >> affect the program's execution.)

    >
    > Even better cast the size_t value to unsigned long and print with
    > "%lu", so it works also if size_t is larger than int.
    >
    >> The gcc printf man page indicates that "%zu", "%zx", etc. tell
    >> the compiler that the variable has type size_t, whatever size_t
    >> happens to be. Is "z" part of the C standard or is it a gcc
    >> extension? If the former, at what point did "z" become part of C?

    >
    > With the C99 standard. It says:
    >
    > 'z' Specifies that a following 'd', 'i', 'o', 'u', 'x', or
    > 'X' conversion specifier applies to a 'size_t' or the
    > corresponding signed integer type argument; or that a
    > following 'n' conversion specifier applies to a pointer
    > to a signed integer type corresponding to 'size'_t argu-
    > ment.


    However this is actually implemented in the library, which supplies
    a large interpreter for the printf formatting system [1]. This
    means that you can have a compiler (such as gcc executed with
    -std=C99) that accepts the code, and have things fail at run time.
    The libraries are usually supplied with the operating system. Be
    warned.

    [1] This large interpreter is the reason to avoid printf and
    friends when compact code is required. Specialized routines
    outputting via putc or fputs can save a good deal of code space,
    especially in embedded systems.

    --
    Some informative links:
    news:news.announce.newusers
    http://www.geocities.com/nnqweb/
    http://www.catb.org/~esr/faqs/smart-questions.html
    http://www.caliburn.nl/topposting.html
    http://www.netmeister.org/news/learn2quote.html
     
    CBFalconer, May 12, 2005
    #4
  5. David Mathog

    tedu Guest

    Keith Thompson wrote:

    > For C90, the best way to print a size_t value is to use "%lu" and

    cast
    > the value to unsigned long. This will *almost* always work in C99 as
    > well. The only case where it won't is when size_t is bigger than
    > unsigned long (I don't know of any platforms where this is the case)
    > *and* the specific value you're printing exceeds ULONG_MAX.


    64 bit Windows. long is still 32 bits. see
    http://www.microsoft.com/whdc/driver/kernel/64bit_chklist.mspx for more
    fun.
     
    tedu, May 12, 2005
    #5
  6. "tedu" <> writes:
    > Keith Thompson wrote:
    >
    >> For C90, the best way to print a size_t value is to use "%lu" and

    > cast
    >> the value to unsigned long. This will *almost* always work in C99 as
    >> well. The only case where it won't is when size_t is bigger than
    >> unsigned long (I don't know of any platforms where this is the case)
    >> *and* the specific value you're printing exceeds ULONG_MAX.

    >
    > 64 bit Windows. long is still 32 bits. see
    > http://www.microsoft.com/whdc/driver/kernel/64bit_chklist.mspx for more
    > fun.


    Putting the "backwards" in "backwards compatibility".

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, May 12, 2005
    #6
  7. On 2005-05-12 17:28:00 -0400, Keith Thompson <> said:

    > As Jens Toerring pointed out, the "%zu" format is new in C99. That
    > means that some systems don't yet support it. (Incidentally, there is
    > no "gcc printf man page". printf is part of the runtime library; gcc
    > is just the compiler. gcc typically uses the native runtime library
    > on a given system, so having a current version of gcc is no guarantee
    > that printf() supports "%zu".)
    >
    > For C90, the best way to print a size_t value is to use "%lu" and cast
    > the value to unsigned long. This will *almost* always work in C99 as
    > well. The only case where it won't is when size_t is bigger than
    > unsigned long (I don't know of any platforms where this is the case)


    Just an FYI, for better or worse, it's about to get a lot more common;
    64-bit Windows uses the LLP64 convention. i.e.:

    int: 32-bits
    long: 32-bits
    long long: 64-bits
    size_t: 64-bits


    --
    Clark S. Cox, III
     
    Clark S. Cox III, May 13, 2005
    #7
    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. G Patel
    Replies:
    17
    Views:
    1,076
    Vesa Siivola
    Feb 14, 2005
  2. Guenther Sohler

    Problem with printf formats

    Guenther Sohler, Dec 20, 2005, in forum: C Programming
    Replies:
    16
    Views:
    512
    Joe Wright
    Dec 21, 2005
  3. Sanjay Kulkarni

    Trouble with formats in printf

    Sanjay Kulkarni, Mar 21, 2007, in forum: C Programming
    Replies:
    5
    Views:
    350
    Army1987
    Mar 21, 2007
  4. Alex Vinokur
    Replies:
    9
    Views:
    812
    James Kanze
    Oct 13, 2008
  5. Alex Vinokur
    Replies:
    1
    Views:
    591
Loading...

Share This Page