Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using std::chrono::duration::rep with printf in 32bit and 64bit programs

There is this code:

#include <cstdio>
#include <chrono>

int main()
{
  auto d = std::chrono::microseconds(1).count();
  printf("%lld", d);
  return 0;
}

When this is compiled in 64bit mode, then there is a warning:

main.cpp: In function ‘int main()’:
main.cpp:7:19: warning: format ‘%lld’ expects argument of type ‘long long int’, but argument 2 has type ‘long int’ [-Wformat=]
   printf("%lld", d);
                   ^

This warning is not present when compiling in 32bit mode (with -m32 flag). It looks like that std::chrono::duration::rep is of type long int in 64bit programs and long long int in 32bit programs.

Is there a portable way to print it like %zu specifier for size_t?

like image 500
wulujey Avatar asked Aug 31 '17 11:08

wulujey


4 Answers

As you said that the usage of std::cout is not an option you can cast the value to the smallest needed data type1 here it's long long int2 and use the corresponding conversion specifier:

printf("%lld", static_cast<long long int>(d));

To avoid the explicit cast you can also use the data type directly instead of the auto specifier:

long long int d = std::chrono::microseconds(1).count();
printf("%lld", d);

1 With smallest needed data type I mean the smallest type that can represent the value in both implementations.
2 The long long int type has to be at least 64 bit wide, see here on SO.

like image 143
Andre Kampling Avatar answered Sep 29 '22 20:09

Andre Kampling


Instead of using the auto qualifier, use a fixed size integer int64_t.

#include <cstdio>
#include <chrono>
#include <cinttypes>

int main()
{
    int64_t d = std::chrono::microseconds(1).count();
    printf("%" PRId64 "\n", d);
    return 0;
}
like image 40
Clonk Avatar answered Sep 29 '22 20:09

Clonk


You can cast it to long long int before printing:

#include <cstdio>
#include <chrono>

int main()
{
  auto d = std::chrono::microseconds(1).count();
  printf("%lld", static_cast<long long int>(d));
  return 0;
}

But it seems me that it is better to use std::cout

like image 38
Amadeus Avatar answered Sep 29 '22 20:09

Amadeus


I suggest you use std::cout, since you are in C++. This will be portable.


However, if you must use printf, change this:

printf("%lld", d);

to this:

#include <cinttypes>
printf("%" PRId64 "", d); 

Another approach would be to cast d to the highest data type (which can hold both types), like this:

printf("%lld", static_cast<long long int>(d));
like image 26
gsamaras Avatar answered Sep 29 '22 19:09

gsamaras