printf formats for size_t?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • David Mathog

    #1

    printf formats for size_t?

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

    (void) sprintf(msg,"le ngth 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
    mathog@caltech. edu
  • Jens.Toerring@physik.fu-berlin.de

    #2
    Re: printf formats for size_t?

    David Mathog <mathog@caltech .edu> wrote:[color=blue]
    > size_t varies from system to system. This occasionally leads to
    > coding issues such as:[/color]
    [color=blue]
    > (void) sprintf(msg,"le ngth of buffer: %d",strlen(msg) );[/color]
    [color=blue]
    > 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.)[/color]

    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.
    [color=blue]
    > 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?[/color]

    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 ___ Jens.Toerring@p hysik.fu-berlin.de
    \______________ ____________ http://www.toerring.de

    Comment

    • Keith Thompson

      #3
      Re: printf formats for size_t?

      David Mathog <mathog@caltech .edu> writes:[color=blue]
      > size_t varies from system to system. This occasionally leads to
      > coding issues such as:
      >
      > (void) sprintf(msg,"le ngth 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?[/color]

      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_Keit h) kst-u@mib.org <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.

      Comment

      • CBFalconer

        #4
        Re: printf formats for size_t?

        Jens.Toerring@p hysik.fu-berlin.de wrote:[color=blue]
        > David Mathog <mathog@caltech .edu> wrote:
        >[color=green]
        >> size_t varies from system to system. This occasionally leads to
        >> coding issues such as:[/color]
        >[color=green]
        >> (void) sprintf(msg,"le ngth of buffer: %d",strlen(msg) );[/color]
        >[color=green]
        >> 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.)[/color]
        >
        > 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.
        >[color=green]
        >> 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?[/color]
        >
        > 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.[/color]

        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.annou nce.newusers
        Latest news coverage, email, free stock quotes, live scores and video are just the beginning. Discover more every day at Yahoo!






        Comment

        • tedu

          #5
          Re: printf formats for size_t?

          Keith Thompson wrote:
          [color=blue]
          > For C90, the best way to print a size_t value is to use "%lu" and[/color]
          cast[color=blue]
          > 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.[/color]

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

          Comment

          • Keith Thompson

            #6
            Re: printf formats for size_t?

            "tedu" <tu@zeitbombe.o rg> writes:[color=blue]
            > Keith Thompson wrote:
            >[color=green]
            >> For C90, the best way to print a size_t value is to use "%lu" and[/color]
            > cast[color=green]
            >> 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.[/color]
            >
            > 64 bit Windows. long is still 32 bits. see
            > http://www.microsoft.com/whdc/driver...t_chklist.mspx for more
            > fun.[/color]

            Putting the "backwards" in "backwards compatibility".

            --
            Keith Thompson (The_Other_Keit h) kst-u@mib.org <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.

            Comment

            • Clark S. Cox III

              #7
              Re: printf formats for size_t?

              On 2005-05-12 17:28:00 -0400, Keith Thompson <kst-u@mib.org> said:
              [color=blue]
              > 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)[/color]

              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
              clarkcox3@gmail .com

              Comment

              Working...