8

Or in other words: Could a wrong printf / fprintf decimal integer (%d, %u, %ld, %lld) format string cause a program to crash or lead to undefined behavior?

Cosinder following lines of code:

#include <iostream>
#include <cstdio>

int main() {
    std::cout << sizeof(int) << std::endl
              << sizeof(long) << std::endl;

    long a = 10;
    long b = 20;
    std::printf("%d, %d\n", a, b);

    return 0;
}

Result on 32 bit architecture:

4
4
10, 20

Result on 64 bit architecture:

4
8
10, 20

In any case the program prints the expected result. I know, if the long value exceeds the int range, the program prints wrong numbers – which is ugly, but doesn't effect the main purpose of the program –, but beside this, could anything unexpected happen?

Christian Ammer
  • 7,464
  • 6
  • 51
  • 108
  • 1
    Possible duplicate of [What happens when I use the wrong format specifier?](https://stackoverflow.com/questions/16864552/what-happens-when-i-use-the-wrong-format-specifier) – phuclv Jan 14 '18 at 03:17

5 Answers5

11

What can happen if printf is called with a wrong format string?

Anything can happen. It is Undefined behavior!
Undefined behavior means that anything can happen. It may show you results which you expect or it may not or it may crash. Anything can happen and you can blame no one but yourself about it.

Reference:

c99 Standard: 7.19.6.1:
para 9:

If a conversion specification is invalid, the behavior is undefined.225) If any argument is not the correct type for the corresponding coversion specification, the behavior is undefined.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • 4
    do you mean that `char c=1;printf("%d",c);` is undefined behavior also ? – rondino Aug 08 '16 at 16:48
  • 5
    "you can blame no one but yourself about it" -- finally I have a good response to this; see "Blaming the programmer" at the end of [this blog post](https://eev.ee/blog/2016/12/01/lets-stop-copying-c/). – Kyle Strand Dec 16 '16 at 23:45
  • 4
    @rondino No because `c` gets promoted to `int` before it is passed to `printf()` See "default argument promotions". – Swordfish May 19 '19 at 23:09
3

It's undefined behaviour - there is nothing in the specification telling the compiler designer (or C library designer) how this should be handled, and thus they are allowed to do anything.

In practice, is one of those where it's entirely up to the interpretation of the numbers, and most likely, you won't ever get anything GOOD from doing this. The really bad ones are when you mix string with integer formatting - strings will print nicely as (strange, perhaps) numbers, but numbers are unlikely to "work" when passed as strings - because a string is a pointer to the address of the first character - and most numbers are not valid pointers in a typical system, so it will crash.

But there is no guarantee of anything. In your 64-bit example, it's clear that the number is "little endian". Try the same thing with 0x100000000, and it will print 0 - because the rest of the number is lost.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
2

Oh yes - printf depends on the format string to determine the size and type of the variable to fetch next. When the format string is wrong it may try to fetch a variable that isn't even there, with all consequences that may have.

fvu
  • 32,488
  • 6
  • 61
  • 79
2

Anything can happen if printf is called with a wrong format string . Its undefined behaviour and one should never rely on undefined behaviour.

-3

Don't use printf

printf is a relic of the C days, and is no longer needed... Use std::cout and I/O manipulators instead.

Alex Chamberlain
  • 4,147
  • 2
  • 22
  • 49
  • 1
    This is in general a sound advice but it does not answer the Q. – Alok Save Jan 24 '13 at 15:11
  • 1
    @AlokSave Very true, but I think the OP asked the wrong question. – Alex Chamberlain Jan 24 '13 at 15:12
  • 4
    There are no wrong questions. There are badly formatted questions and correctly formatted ones. Just ignore the C++ tag on the Q and this becomes a perfectly valid Q. – Alok Save Jan 24 '13 at 15:14
  • 2
    In our embedded code, we use c++ but don't use iostreams, We use snprintf and vsnprintf in conjunction with custom logging functions/methods. So the printf family is still quite relevant and useful. Also note, that the entire standard c library is "relic" of the old C days. It is widely used, maintained and remains useful to large numbers of developers around the world. – Craig B Nov 26 '19 at 20:25