38

Which character should be used for ptrdiff_t in printf?

Does C standard clearly explains how to print ptrdiff_t in printf? I haven't found any one.

int a = 1;
int b = 2;

int* pa = &a;
int* pb = &b;

ptrdiff_t diff = b - a;

printf("diff = %?", diff); // % what?
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
Amir Saniyan
  • 13,014
  • 20
  • 92
  • 137

3 Answers3

37

It's %td. See here.

trojanfoe
  • 120,358
  • 21
  • 212
  • 242
  • 1
    That reference doesn't appear complete; the `t` character is a length modifier of the `d` type specifier. I would also suggest you specify Visual Studio in your question if that is the platform you are interested in. – trojanfoe Oct 31 '11 at 13:45
  • 7
    `%td` is standard. Visual Studio's C compiler doesn't conform to the current C standard. – CB Bailey Oct 31 '11 at 13:46
  • 3
    @AmirSaniyan: The `t` is a size specifier, not a type (the type is `d` here). [Apparently](http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx) `I` should be used as the size specifier for `ptrdiff_t` with the Microsoft implementation (so `%Id`), which is nonstandard. – caf Oct 31 '11 at 13:47
  • 12
    @AmirSaniyan: **No.** `%td` is completely standard (§7.19.6.1, paragraph 7). As Microsoft does not actually provide a C compiler, the behavior of VS has nothing to do with what is standard or not. – Stephen Canon Oct 31 '11 at 13:49
  • 2
    Visual Studio 2015 supports both `%zu` and `%td` (not properly documented on MSDN, but both test out OK). – vladr Dec 18 '17 at 21:34
17

C11 draft explains the length modifier for ptrdiff_t in 7.21.6.1 7 "The fprintf function"

t
Specifies that a following d, i, o, u, x, or X conversion specifier applies to a ptrdiff_t or the corresponding unsigned integer type argument; or that a following n conversion specifier applies to a pointer to a ptrdiff_t argument.

Use "%td" as in the following: Credit: @trojanfoe

ptrdiff_t diff = b - a;
printf("diff = %td", diff);

If the compiler does not support "%td", cast to a signed type - the longer, the better. Then insure the alternative format and argument match.

// Note the cast
printf("diff = %lld", (long long) diff); // or
printf("diff = %ld", (long) diff);

Ref format specifiers

Community
  • 1
  • 1
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
7

Use %td and if your compiler does not support it, you should try %ld (also cast the input to long).

masoud
  • 55,379
  • 16
  • 141
  • 208