5

Consider this code:

typedef int64_t Blkno;
#define BLKNO_FMT "%lld"
printf(BLKNO_FMT, (Blkno)some_blkno);

This works well and fine on x86. On x64, int64_t is actually a long, rather than a long long, and while long and long long are the same size on x64, the compiler generates an error:

src/cpfs/bitmap.c:14: warning: format ‘%lld’ expects type ‘long long int’, but argument 6 has type ‘Blkno’

  1. How can I tell printf that I'm passing a 64bit type?
  2. Is there some better way to standardize specs for user types than using a #define like BLKNO_FMT as above?
Matt Joiner
  • 112,946
  • 110
  • 377
  • 526

2 Answers2

10

Use PRId64 from inttypes.h.

Blkno is not a very good type name. BLKNO_FMT could be replaced by PRIdBLKNO.

#include <inttypes.h>
#include <stdio.h>

typedef int64_t Blkno;
#define PRIdBLKNO PRId64

int main(void) {
  printf("%" PRIdBLKNO "\n", (Blkno)1234567890);
  return 0;
}
jfs
  • 399,953
  • 195
  • 994
  • 1,670
  • The `(Blkno)` cast is pointless if you have used the right format specifier. – user502515 Dec 10 '10 at 10:37
  • 3
    It's not pointless, integer arguments to a variadic functions are not promoted to long long. – dreamlax Dec 10 '10 at 10:41
  • @user502515: Without `(Blkno)` the compiler produces `'warning: conversion specifies type 'long' but the argument has type 'int' [-Wformat]'` – jfs Dec 10 '10 at 10:43
  • @user502515: See C99 §6.3.1.1/2 and §6.5.2.2/6 regarding integer promotions and *default argument promotions*. – dreamlax Dec 10 '10 at 10:48
  • The cast is to demonstrate that some_blkno is of type Blkno. I was not under the impression that the cast was actually necessary. If this is incorrect, please let me know!! – Matt Joiner Dec 10 '10 at 16:21
  • I'll add that in @J.F. Sebastion's example, the cast **is** necessary, as the literal is an int. However some_blkno is of type Blkno already, the cast should not be necessary. – Matt Joiner Dec 10 '10 at 16:23
  • @Matt Joiner: Blkno looks like čtvrthrst at a glance; both are pronounceable once deciphered. – jfs Dec 10 '10 at 22:30
  • @J.F. Sebastion: I've spent far too many hours trying to come up with the perfect variable and type names, now I just use whatever seems reasonable and quick and lengthen them only as required. – Matt Joiner Dec 11 '10 at 06:34
  • 1
    @Matt Joiner: There are only two hard things in CS: cache invalidation and naming things (by Phil Karlton http://martinfowler.com/bliki/TwoHardThings.html) – jfs Dec 11 '10 at 17:48
  • @Matt Joiner: To paraphrase The Zen of Python: If the thing is hard to name, it's a bad abstraction. If the thing is easy to name, it may be a good abstraction. http://www.python.org/dev/peps/pep-0020/ – jfs Dec 11 '10 at 17:55
  • @J.F.Sebastian: Agreed on CS and Python statements. I don't know what you mean by čtvrthrst. Is your name a reference to Blade Runner? – Matt Joiner Jan 04 '12 at 03:19
0

These types are not 64-bit types. They're platform-specific. The only portable way to print them is to cast to intmax_t or uintmax_t and use the correct format specifiers for to print those types.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711