Thread: An interesting code of "printf"

  1. #1
    Registered User
    Join Date
    Apr 2007
    Posts
    284

    An interesting code of "printf"

    Code:
    #include <stdint.h>                                                             
    #include <string>                                                               
    #include <stdio.h>                                                              
                                                                                    
    int main(){                                                                     
        uint64_t a=3;                                                              
        std::size_t b = 91;                                                        
        printf("%llu,%llu\n",a, b);                                               
        printf("%llu,%llu\n",b, a);                                               
        return 0;                                                                   
    }
    As you can see, the first line
    Code:
        printf("%llu,%llu\n",a, b);
    prints out weird output for b, because std::size_t is not %llu
    But when you switch the position of a and b, as in the second line:
    Code:
        printf("%llu,%llu\n",b, a);
    The output of a is also wrong. What happened?

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Right, depending on the architecture you compile for (e.g. 32 or 64-bit x86), size_t may be a 32 or a 64-bit value. Since the printf implementation reads 64 bits to make the %llu output, it will not read the correct data if one of those two are a 32-bit value.

    If you printf("%z", sizeof(size_t)), it should show you the size of size_t.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    . . . with C99, of course. &#37;z doesn't exist in C89, nor C++ for that matter.

    Something like this would work just about anywhere:
    Code:
    printf("%lu\n", sizeof(size_t));
    Of course, in C++, you could let cout handle the type.

    Note that %llu is also C99.

    @OP: Except for <string>, your code looks very much like C. If most of your code is C, perhaps you should consider removing this header file and any other C++-specific stuff and compiling as C . . . .
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  4. #4
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by dwks View Post
    . . . with C99, of course. %z doesn't exist in C89, nor C++ for that matter.

    Something like this would work just about anywhere:
    Code:
    printf("%lu\n", sizeof(size_t));
    .
    It would be safer to do:
    Code:
    printf("%lu\n", (unsigned long)sizeof(size_t));
    Lying to printf is bad.

    Instead it is better to cast size_t to a type of your choosing (like unsigned long).
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  5. #5
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    Quote Originally Posted by matsp View Post
    If you printf("&#37;z", sizeof(size_t)), it should show you the size of size_t.
    The length modifier (the z) is optional, but AFAIK, the type specifier (u) is not. So it should be like this: printf("%zu", sizeof(size_t))

    edit:

    printf("%llu,%llu\n",a, b);

    llu is the conversion specification for a long long unsigned int, not a uint64_t.

    Use PRIu64 in inttypes.h (or cinttypes) instead:

    printf(PRIu64 ",%zu\n",a, b);

    edit2:

    Quote Originally Posted by dwks View Post
    . . . with C99, of course. %z doesn't exist in C89, nor C++ for that matter.
    Quote Originally Posted by C++ Chapter 17
    9 The descriptions of many library functions rely on the Standard C99 Library for the signatures and semantics of those
    functions. In all such cases, any use of the restrict qualifier shall be omitted.
    So I think the z length modifier is supported in C++.
    Last edited by robwhit; 02-13-2008 at 10:42 PM.

  6. #6
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by dwks View Post
    . . . with C99, of course. %z doesn't exist in C89
    Note that %llu is also C99.
    If you have %llu, then %zu should also work - sorry about missing the u.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by robwhit View Post
    The length modifier (the z) is optional, but AFAIK, the type specifier (u) is not. So it should be like this: printf("%zu", sizeof(size_t))

    edit:

    printf("%llu,%llu\n",a, b);

    llu is the conversion specification for a long long unsigned int, not a uint64_t.
    Yes, in a 32-bit architecture, uint64_t is probably unsigned long long, whilst in a 64-bit architecture, it may be unsigned long.

    --
    mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    The length modifier (the z) is optional, but AFAIK, the type specifier (u) is not. So it should be like this: printf("&#37;zu", sizeof(size_t))
    If you have %llu, then %zu should also work - sorry about missing the u.
    Thanks for that -- I was wondering why my compiler was complaining about the non-existent "%z" . . .

    So I think the z length modifier is supported in C++.
    I don't think it is. My C++ compiler complains about it, and C++ is a superset of C89, not of C99. C99 was then more or less based on some ideas from C++ . . . IIRC, of course.

    It would be safer to do:
    Code:
    printf("%lu\n", (unsigned long)sizeof(size_t));
    Lying to printf is bad.

    Instead it is better to cast size_t to a type of your choosing (like unsigned long).
    Erg, that's exactly what I meant to put. Oops.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  9. #9
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    The C++ standard was published in 1998, so it can't rely on C99. I think the C++09 draft does, though.

    Something like this would work just about anywhere:
    Except on 64-bit MS compilers, where long is still 32 bits.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  10. #10
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by CornedBee View Post
    The C++ standard was published in 1998, so it can't rely on C99. I think the C++09 draft does, though.


    Except on 64-bit MS compilers, where long is still 32 bits.
    But size_t is 64-bit.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  11. #11
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Yes. That's why dwks's snippet would break.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  12. #12
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    I already mentioned that I had intended to cast the value of sizeof() to an unsigned long, which would let sizeof() work on all values up to the limits of that data type. So unless you had a very, very large data type, this would work:
    Code:
    printf("&#37;lu\n", (unsigned long)sizeof(size_t));
    Of course, if sizeof() evaluated to a value larger than ULONG_MAX, the value would wrap.

    [edit] And of course, if you didn't cast the value, strange things might happen. [/edit]
    Last edited by dwks; 02-20-2008 at 01:06 PM.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 7
    Last Post: 11-15-2007, 01:36 AM
  2. Values changing without reason?
    By subtled in forum C Programming
    Replies: 2
    Last Post: 04-19-2007, 10:20 AM
  3. Obfuscated Code Contest: The Results
    By Stack Overflow in forum Contests Board
    Replies: 29
    Last Post: 02-18-2005, 05:39 PM
  4. Obfuscated Code Contest
    By Stack Overflow in forum Contests Board
    Replies: 51
    Last Post: 01-21-2005, 04:17 PM
  5. Interface Question
    By smog890 in forum C Programming
    Replies: 11
    Last Post: 06-03-2002, 05:06 PM