Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange printf behavior

Tags:

c++

iterator

stl

        std::vector<DWORD64> v;
        for(size_t i = init; i < pageSize; ++i)
            v.push_back(i);

        DWORD64 last =  *(v.rbegin());
        DWORD64 first = *(v.begin());

        printf("%d %d \n", last, first);
        printf("%d %d \n", first, last);

outputs:

4095 0
0 0

I can't understand why this printf behaves like that? Neither init or pageSize is 0. I understand that %d is not valid for unsigned long long, but what bothers me is that printf's behavior changes when argument's order change.

like image 268
Karim Agha Avatar asked Dec 22 '22 01:12

Karim Agha


2 Answers

Neither init or pageSize is 0.

Nor is %d a suitable format string specifier for a 64-bit value, I'd bet :-)

More than likely, you'll need to use %ld (if your longs are 64 bit) or %lld (if your long longs are 64 bit) or the fixed-width specifier macros from the latest C standard that I can never remember off the top of my head, assuming they're available in your environment :-)

That whole problem would probably disappear if you embraced C++ rather than that half-ground which many coders seem to exist in (using legacy stuff like stdio.h when better alternatives are available). You should use the type-aware:

std::cout << a << ' ' << b << '\n';

It also helps to have a compiler that's a bit intelligent, and ensure you use that intelligence:

pax$ cat qq.cpp
    #include <iostream>
    #include <vector>
    #include <cstdio>

    int main (void) {
        std::vector<int> v;
        v.push_back (111142);
        v.push_back (314159);
        long long a = *(v.begin());
        long long b = *(v.rbegin());
        printf ("%6d %6d, a then b, bad\n", a, b);
        printf ("%6d %6d, b then a, bad\n", b, a);
        std::cout << a << ' ' << b << ", good\n";
        return 0;
    }

pax$ g++ -Wall -Wextra -o qq qq.cpp
    qq.cpp: In function 'int main()':
    qq.cpp:11: warning: format '%d' expects type 'int', but argument 2
        has type 'long long int'
    qq.cpp:11: warning: format '%d' expects type 'int', but argument 3
        has type 'long long int'
    : : : : :
    qq.cpp:12: warning: format '%d' expects type 'int', but argument 3
        has type 'long long int'

pax$ ./qq
    111142 0,      a then b, bad
    314159 0,      b then a, bad
    111142 314159, good

For those truly interested in the mechanics as to why the values change based on their order in the printf, see this answer.

It goes into detail about what things (and more importantly, the sizes of those things) get pushed on the stack, comparing them with what you told printf would be there.

Long story writ short: you lied to printf so it treated you the same way your significant other would, had you been caught lying to them :-)

like image 70
paxdiablo Avatar answered Dec 24 '22 02:12

paxdiablo


First printf in fact prints the LO and HI DWORDs of the DWORD64 variable last (which is 4095, i believe). Second printf prints the LO and HI DWORDs of the DWORD64 variable first (which is 0). The second DWORD64 parameter is ignored in both lines...

like image 26
Malkocoglu Avatar answered Dec 24 '22 03:12

Malkocoglu