Thread: Using a size_t variable as a width and precision modifier in printf

  1. #1
    Registered User
    Join Date
    Jul 2009
    Posts
    5

    Question Using a size_t variable as a width and precision modifier in printf

    OK, the title might sound a bit confusing. I'm currently converting code to work on 64 bit machines. One problem I'm having right now is the following call to printf:

    Code:
    int readLen;
    pLine = fgetln( pFile, &readLen );
    printf(" %*.*s", readLen, readLen, pLine );
    This is the code working on a 32 bit machine. But fgetln requires a size_t argument so I changed it to:
    Code:
    size_t readLen;
    pLine = fgetln( pFile, &readLen );
    printf(" %*.*s", readLen, readLen, pLine );
    Now the printf doesn't work any more, because the width and precision modifiers have to be of type int (see printf - C++ Reference)

    Can someone tell me what's the best way to solve this problem (i.e. get the printf working with the width and precision modifiers)?

    Thanks a lot!

  2. #2
    Webhead Spidey's Avatar
    Join Date
    Jul 2009
    Posts
    285
    size_t is basically just an unsigned int. So, I believe %d works on it. But the proper specifier is %u.
    But your not really printing the data and just using it as a width/precision modifier. Did you try casting it ?

  3. #3
    Registered User
    Join Date
    Jul 2009
    Posts
    5

    Post

    I tried casting it to uint32 and the compiler doesn't issue a warning any more. But what in the case that readLen is > INT_MAX? It should never happen, but is it safe to just assume that?). I'm looking for some best practices here. So would the best practice be this?

    Code:
    if (readLen < INT_MAX) {
      printf(" %*.*s", readLen, readLen, pLine );
    } else {
        printf(" %s", pLine );
    }
    Sorry if this is a stupid question, this is the first time I ever ported 32 bit code to work on 64 bit machines and so I'm a bit unsure about a few things.

  4. #4
    C++11 User Tux0r's Avatar
    Join Date
    Nov 2008
    Location
    Sweden
    Posts
    135
    Code:
    %zd
    .

  5. #5
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by Spidey View Post
    size_t is basically just an unsigned int. So, I believe %d works on it. But the proper specifier is %u.
    But your not really printing the data and just using it as a width/precision modifier. Did you try casting it ?
    stdlib.h - Wikipedia, the free encyclopedia

    You might want to check the size of size_t on your platform. Maybe you need %ul instead?
    "I am probably the laziest programmer on the planet, a fact with which anyone who has ever seen my code will agree." - esbo, 11/15/2008

    "the internet is a scary place to be thats why i dont use it much." - billet, 03/17/2010

  6. #6
    C++11 User Tux0r's Avatar
    Join Date
    Nov 2008
    Location
    Sweden
    Posts
    135
    Quote Originally Posted by cpjust View Post
    stdlib.h - Wikipedia, the free encyclopedia

    You might want to check the size of size_t on your platform. Maybe you need %ul instead?
    Just one post above you.

  7. #7
    Registered User
    Join Date
    Jul 2009
    Posts
    5
    Quote Originally Posted by Tux0r View Post
    Code:
    %zd
    .
    That's not what I want. I want to use it for the width and precision modifiers, which are given as "*.*"

  8. #8
    C++11 User Tux0r's Avatar
    Join Date
    Nov 2008
    Location
    Sweden
    Posts
    135
    Quote Originally Posted by AnTriber View Post
    That's not what I want. I want to use it for the width and precision modifiers, which are given as "*.*"
    C formats never stop to amuse me

  9. #9
    Registered User ssharish2005's Avatar
    Join Date
    Sep 2005
    Location
    Cambridge, UK
    Posts
    1,732
    >But fgetln requires a size_t argument so I changed it to
    Is there any reason why you changes it from int to size_t, when int was working fine? size_t clame to have some problem on a 64 bit machines. Have a look at the wike link provided.

    ~ssharish
    Life is like riding a bicycle. To keep your balance you must keep moving - Einstein

  10. #10
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    Quote Originally Posted by AnTriber View Post
    I tried casting it to uint32 and the compiler doesn't issue a warning any more. But what in the case that readLen is > INT_MAX? It should never happen, but is it safe to just assume that?). I'm looking for some best practices here. So would the best practice be this?

    Code:
    if (readLen < INT_MAX) {
      printf(" %*.*s", readLen, readLen, pLine );
    } else {
        printf(" %s", pLine );
    }
    That second printf() is not safe, because fgetln() (assuming you're using a BSD-like fgetln()) will not create a string.

    Casting to uint32 is not right, because printf(), as you've mentioned, expects an int for specifying the field width and precision. So, cast to int. If you're worried that it will be larger than INT_MAX then yes, you'll want to do a test. If it is larger, you'll have to find some way of printing. Loop and putc(); malloc() memcpy() null terminate and printf(); or whatever. No matter what you do, though, it'll be inefficient because INT_MAX on a 32-bit system is likely going to be 2GB.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Format Precision & Scale
    By mattnewtoc in forum C Programming
    Replies: 1
    Last Post: 09-16-2008, 10:34 AM