<p>In the C++ standard library, the <a href="https://en.cppreference.com/w/cpp/utility/format/format" rel="nofollow noreferrer"><code>format</code></a> and <a href="https://en.cppreference.com/w/c/io/fprintf" rel="nofollow noreferrer"><code>printf</code></a> functions specifically accept extraneous arguments:</p>
<blockquote>
<p>It is not an error to provide more arguments than the format string
requires: <code>std::format(&quot;{} {}!&quot;, &quot;Hello&quot;, &quot;world&quot;, &quot;something&quot;); // OK</code>,
produces <code>&quot;Hello world!&quot;</code></p>
</blockquote>
<p>Why did the C++ language designers make this decision? It has the downside that the compiler cannot detect obvious mistakes at compile-time.</p>

<language-design><c++>
Why does C++ allow extra arguments to printf?
CC BY-SA 4.0
2023-12-09T13:32:39.677Z
`std::format` and `printf` are very different functions; which do you mean to ask about? For printf it's just because of how C's varargs work.
Bbrk24
CC BY-SA 4.0
2023-12-11T16:39:50.837Z
GCC supports compile-time checking of `printf`-style format strings by declaring the function with the `format` [attribute](https://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Function-Attributes.html).
dan04
CC BY-SA 4.0
2024-01-10T04:57:17.047Z
If the designers of printf had wished their compiler to detect obvious mistakes at compile time, they would have designed a very different language than C!
Eric Lippert
<h2>printf</h2>
<p>With respect to <code>printf</code>, the C++ committee didn't really have a lot of choice. <code>printf</code> was &quot;inherited&quot; from C, and its use accepted as-is, for the sake of backward compatibility.</p>
<h2>std::format</h2>
<p>I haven't found any notes about discussion of this specific rule with respect to <code>std::format</code> (but it's possible it was there and I missed it--the <code>std::format</code> spec went through 10 revisions before being incorporated into the standard, and there were a number of related papers as well (see links below).</p>
<p>That leaves us able to make only an educated guess<sup>1</sup> about why they chose what they did. My guess would be that the reasoning was pretty simple: <code>printf</code> already displays this behavior. Maintaining similar behavior in this respect allows code that currently used <code>printf</code> to be converted to use <code>std::format</code> more easily, by editing only conversion specifiers in the format string, without worrying about architectural-level decisions that might result in an argument that might sometimes be unused.</p>
<h2>Error Detection</h2>
<p>This rule does not prevent detection of discrepancies between format strings and argument count. It merely means such discrepancies would be reported as warnings, rather than errors. Technically, they could actually be reported as errors if you really wanted to, but I'm reasonably certain most C++ programmers would find that somewhat surprising. The standard requires that any program that contains an diagnosable error produce at least one &quot;diagnostic&quot;, but doesn't go into detail about what constitutes a &quot;diagnostic&quot;. Many compilers need a fairly specific set of compiler flags to get their closest approximation of conforming behavior in any case.</p>
<hr />
<sup>
1. But it is at least somewhat educated--I've attended meetings of the C++ standards committee, read many of the proposals since the mid-1990's or so, and contributed some changes to both the C and C++ standards.
</sup>
<p>
<h1>References</h1>
<p><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0645r9.html" rel="noreferrer">https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0645r9.html</a></p>
<p><a href="https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2572r1.html" rel="noreferrer">https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2572r1.html</a></p>
<p><a href="https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2713r1.html" rel="noreferrer">https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2713r1.html</a></p>
<p><a href="https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2675r1.pdf" rel="noreferrer">https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2675r1.pdf</a></p>

CC BY-SA 4.0
2023-12-10T23:02:23.913Z
2023-12-11T18:29:32.083Z
2023-12-11T18:29:32.083Z
Jerry Coffin
<p>The mechanism for processing variadic argument lists in C++ was inherited from C. This mechanism does not provide a way to determine the number of arguments that were supplied, it simply supports sequential access to each argument.</p>
<p>So variadic formatting functions work by using the format string to guide iteration over the variadic arguments. Since there's nothing wrong with not fetching all the provided arguments, nothing bad can happen if the format string has fewer placeholders than arguments -- the extra arguments are simply ignored.</p>
<p>There's nothing preventing a compiler from doing sanity checks that aren't required by the language, and many popular compilers issue warnings for this type of mistake. There are also typically compiler options (e.g. GCC's <code>-Werror</code>) that will convert warnings into fatal errors.</p>
<p>Note that this check can only be done at compile time when the format string is constructed at compile time. You can pass a dynamically-constructed format string to <code>printf()</code>. Since it's not possible to create the argument list dynamically, it may be useful to pass extra arguments that might not be used by some of the dynamically-generated format strings.</p>
<p>Actually, C++'s <a href="https://en.cppreference.com/w/cpp/language/parameter_pack" rel="nofollow noreferrer">parameter pack</a> mechanism improves on C's <code>stdarg.h</code> feature, and provides a <code>std::sizeof...</code> operator that allows the program to get the number of arguments passed. <code>std::format()</code> uses this, so it would be possible for it to check the number of arguments, and there's less reason for the spec to be so liberal. I can only speculate on why they didn't, perhaps to ease the transition from <code>printf()</code> to <code>std::format()</code>.</p>

CC BY-SA 4.0
2023-12-11T21:11:35.353Z
2023-12-13T19:58:22.957Z
2023-12-13T19:58:22.957Z
Barmar
CC BY-SA 4.0
2023-12-13T16:43:54.087Z
@G.Sliepen Thanks, I just glanced at the linked page. Could it use `sizeof...` to be able to compare the number of arguments with the number of format string placeholders?
Barmar
CC BY-SA 4.0
2023-12-13T19:58:32.903Z
Thanks, I've updated the answer to mention this.
Barmar
<p>C++ allows extra arguments to <code>printf</code> because it follows at least a few of the fundamental principles of C, from which <code>printf</code> was inherited.</p>
<p>The fundamental principle of C which is of interest here is that the compiler should be kept as separate as possible from the standard library. In C it was possible to develop systems without using the standard library at all; you could re-invent whatever parts of the standard library you needed by issuing native calls to your target environment, and you could build any kind of system you could imagine. It would not be portable, but that's a different story.</p>
<p>In early versions of C++ the same held true, though it was a bit more difficult. I do not know whether this is possible in modern C++, but the general philosophy is still there.</p>
<p>Because of this fundamental principle, the compiler does not have, or is not expected to have, any knowledge whatsoever of the <code>printf</code> function, or of any other standard library function. The language provides a syntax for variadic functions, so that functions like <code>printf</code> can be written, and that is as far as the language goes.</p>
<p>This is a concept that many folks coming from other languages found hard to grasp: Strictly speaking, the question &quot;how do you print something in C?&quot; does not make sense, and it is only answerable in a roundabout way: technically, you do not print anything in C, because C is a language, and it is not concerned with such mundane concepts like printing. However, the creators of the language were so kind as to provide a standard library, and in order to print something using the C standard library you use the <code>printf</code> function.</p>
<p>So, since the compiler has no knowledge of the <code>printf</code> function, it cannot have a saying as to whether the number of arguments that you are passing to it is correct or not. It just does not know, and does not care.</p>
<p>Compilers that do, nonetheless, issue warnings on improper use of <code>printf</code> are performing a bit of a blasphemy: they are assuming knowledge of the fact that you are most likely using the standard libraries, which is above and beyond their duties, and they do it for the sake of the programmer's convenience.</p>

CC BY-SA 4.0
2023-12-12T00:30:24.853Z
2023-12-12T00:30:24.853Z
Mike Nakis
CC BY-SA 4.0
2023-12-18T21:12:28.173Z
When the compiler finds for example #include <stdio.h> then it knows that printf is the standard library printf (or it could be a macro or maybe static function but then you shouldn’t get the warning).
gnasher729
CC BY-SA 4.0
2023-12-19T01:26:03.500Z
@gnasher729 I am not sure I understand what point you are trying to make.
Mike Nakis
<p>The best reason to not raise errors when extra arguments are provided, I think, is to allow the format string to be easily changed ─ or perhaps, provided dynamically ─ without having to change the argument list.</p>
<p>Note that the same is true in other languages such as Python, so this isn't a quirk of C++:</p>
<pre class="lang-python prettyprint-override"><code>&gt;&gt;&gt; '{} {}'.format('Hello', 'world', 'something')
'Hello world'
</code></pre>
<p>The upside is that you can specify the format string elsewhere, or e.g. load it at runtime (useful for internationalisation), and it can be edited without having to edit the code which provides the arguments. For example:</p>
<pre class="lang-python prettyprint-override"><code>WELCOME_STRING = '{0} version {1}\n\n{3}'

# ...

print(WELCOME_STRING.format(PROGRAM_NAME, PROGRAM_VERSION, COMPILED_DATE, LICENSE_TEXT))
</code></pre>
<p>This works even better with keyword-arguments in the format string, although C++ doesn't support those (presumably because libc doesn't):</p>
<pre class="lang-python prettyprint-override"><code>WELCOME_STRING = '{PROGRAM_NAME} version {PROGRAM_VERSION}\n\n{LICENSE_TEXT}'
</code></pre>

CC BY-SA 4.0
2023-12-09T12:48:38.120Z
2023-12-09T12:48:38.120Z
kaya3
CC BY-SA 4.0
2023-12-09T12:59:27.207Z
You can't have a dynamic string in C++ though, it has to be known at compile time
mousetail 'he-him'
CC BY-SA 4.0
2023-12-09T13:04:31.370Z
Thank you for your answer, but tbh, it makes very weak argument.
Deborah C
CC BY-SA 4.0
2023-12-09T13:28:50.033Z
@mousetail What do you mean that you can't have a dynamic string in C++? You can get one in all the same ways you can in C, like loading from a file or using a function like `scanf`. `std::string` can be created from a `const char*`.
Bbrk24
CC BY-SA 4.0
2023-12-09T14:15:25.303Z
@Bbrk24 https://ato.pxeger.com/run?1=fVLNTgIxGIzXPsVnvUCARDyZZVkSEw8cfACjZlNLF76k25r-QAjhSbxw8aY-kK_hC7i7XWGTBZr00JnJTOdr37_4m_S23Omc8-8nOrBuNua93s01fdl9eJcNbn8ufq9QcelnAuJMm5y5hBwQ1NYZwfImViCo5m0kXaJYJQQIKgc5Q9Xpkg2BYhWxURREkKGxLlUsF6MWJ1mb4to7iGOg98oJA2vtTfCAUkibSlSQJMcDjrmUaadMzt5kWvfeG0xqh7L4aoF8kYZJtn1PsbV1dQhspymFCdDHqrmXsooEtLAZbi-fFYXon9yPpWBpvzGJ_qFQd0TINrx9_QV2n3f6lTwwI8WaDAP2Bw
mousetail 'he-him'
CC BY-SA 4.0
2023-12-09T14:17:23.897Z
What I mean is, in printf/format specifically, the string has to be static.
mousetail 'he-him'
CC BY-SA 4.0
2023-12-09T14:50:07.750Z
@mousetail yes with format (at least until C++26 comes out with runtime_format), not with printf: https://godbolt.org/z/zPT8MvWWv
kouta-kun
CC BY-SA 4.0
2023-12-09T17:17:51.700Z
@DeborahC If you're reading my answer as an *argument in favour* of the language being designed this way, then perhaps you misunderstood your own question. You asked for reasons why it would be designed that way, and I gave you what I think is the best reason. I haven't argued that a language *should* be designed any particular way.
kaya3
CC BY-SA 4.0
2023-12-09T17:33:25.743Z
The question asks “Why did the C++ language designers make this decision?” This answer does not answer that question; it’s just a guess (and one I don’t think is particularly likely to be the explanation, for what it’s worth).
Alexis King
# Why does C++ allow extra arguments to printf?
Posted by: username_0 on 2023-12-09
In the C++ standard library, the [`format`](https://en.cppreference.com/w/cpp/utility/format/format) and [`printf`](https://en.cppreference.com/w/c/io/fprintf) functions specifically accept extraneous arguments:

> It is not an error to provide more arguments than the format string
> requires: `std::format("{} {}!", "Hello", "world", "something"); // OK`,
> produces `"Hello world!"`

Why did the C++ language designers make this decision? It has the downside that the compiler cannot detect obvious mistakes at compile-time.
**Tags:** language-design c++
> **Comments:**
> **username_1**: `std::format` and `printf` are very different functions; which do you mean to ask about? For printf it's just because of how C's varargs work.  
> **username_2**: GCC supports compile-time checking of `printf`-style format strings by declaring the function with the `format` [attribute](https://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Function-Attributes.html).  
> **username_3**: If the designers of printf had wished their compiler to detect obvious mistakes at compile time, they would have designed a very different language than C!  
---
## 4 answers
### Answer by username_4 on 2023-12-10. Score: 10
## printf

With respect to `printf`, the C++ committee didn't really have a lot of choice. `printf` was "inherited" from C, and its use accepted as-is, for the sake of backward compatibility.

## std::format

I haven't found any notes about discussion of this specific rule with respect to `std::format` (but it's possible it was there and I missed it--the `std::format` spec went through 10 revisions before being incorporated into the standard, and there were a number of related papers as well (see links below).

That leaves us able to make only an educated guess1 about why they chose what they did. My guess would be that the reasoning was pretty simple: `printf` already displays this behavior. Maintaining similar behavior in this respect allows code that currently used `printf` to be converted to use `std::format` more easily, by editing only conversion specifiers in the format string, without worrying about architectural-level decisions that might result in an argument that might sometimes be unused.

## Error Detection

This rule does not prevent detection of discrepancies between format strings and argument count. It merely means such discrepancies would be reported as warnings, rather than errors. Technically, they could actually be reported as errors if you really wanted to, but I'm reasonably certain most C++ programmers would find that somewhat surprising. The standard requires that any program that contains an diagnosable error produce at least one "diagnostic", but doesn't go into detail about what constitutes a "diagnostic". Many compilers need a fairly specific set of compiler flags to get their closest approximation of conforming behavior in any case.

---

1. But it is at least somewhat educated--I've attended meetings of the C++ standards committee, read many of the proposals since the mid-1990's or so, and contributed some changes to both the C and C++ standards.

# References

<https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0645r9.html>

<https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2572r1.html>

<https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2713r1.html>

<https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2675r1.pdf>
---
### Answer by username_5 on 2023-12-11. Score: 5
The mechanism for processing variadic argument lists in C++ was inherited from C. This mechanism does not provide a way to determine the number of arguments that were supplied, it simply supports sequential access to each argument.

So variadic formatting functions work by using the format string to guide iteration over the variadic arguments. Since there's nothing wrong with not fetching all the provided arguments, nothing bad can happen if the format string has fewer placeholders than arguments -- the extra arguments are simply ignored.

There's nothing preventing a compiler from doing sanity checks that aren't required by the language, and many popular compilers issue warnings for this type of mistake. There are also typically compiler options (e.g. GCC's `-Werror`) that will convert warnings into fatal errors.

Note that this check can only be done at compile time when the format string is constructed at compile time. You can pass a dynamically-constructed format string to `printf()`. Since it's not possible to create the argument list dynamically, it may be useful to pass extra arguments that might not be used by some of the dynamically-generated format strings.

Actually, C++'s [parameter pack](https://en.cppreference.com/w/cpp/language/parameter_pack) mechanism improves on C's `stdarg.h` feature, and provides a `std::sizeof...` operator that allows the program to get the number of arguments passed. `std::format()` uses this, so it would be possible for it to check the number of arguments, and there's less reason for the spec to be so liberal. I can only speculate on why they didn't, perhaps to ease the transition from `printf()` to `std::format()`.
> **Comments:**
> **username_5** (2023-12-13): @G.Sliepen Thanks, I just glanced at the linked page. Could it use `sizeof...` to be able to compare the number of arguments with the number of format string placeholders?  
> **username_5** (2023-12-13): Thanks, I've updated the answer to mention this.  
---
### Answer by username_6 on 2023-12-12. Score: 2
C++ allows extra arguments to `printf` because it follows at least a few of the fundamental principles of C, from which `printf` was inherited.

The fundamental principle of C which is of interest here is that the compiler should be kept as separate as possible from the standard library. In C it was possible to develop systems without using the standard library at all; you could re-invent whatever parts of the standard library you needed by issuing native calls to your target environment, and you could build any kind of system you could imagine. It would not be portable, but that's a different story.

In early versions of C++ the same held true, though it was a bit more difficult. I do not know whether this is possible in modern C++, but the general philosophy is still there.

Because of this fundamental principle, the compiler does not have, or is not expected to have, any knowledge whatsoever of the `printf` function, or of any other standard library function. The language provides a syntax for variadic functions, so that functions like `printf` can be written, and that is as far as the language goes.

This is a concept that many folks coming from other languages found hard to grasp: Strictly speaking, the question "how do you print something in C?" does not make sense, and it is only answerable in a roundabout way: technically, you do not print anything in C, because C is a language, and it is not concerned with such mundane concepts like printing. However, the creators of the language were so kind as to provide a standard library, and in order to print something using the C standard library you use the `printf` function.

So, since the compiler has no knowledge of the `printf` function, it cannot have a saying as to whether the number of arguments that you are passing to it is correct or not. It just does not know, and does not care.

Compilers that do, nonetheless, issue warnings on improper use of `printf` are performing a bit of a blasphemy: they are assuming knowledge of the fact that you are most likely using the standard libraries, which is above and beyond their duties, and they do it for the sake of the programmer's convenience.
> **Comments:**
> **username_7** (2023-12-18): When the compiler finds for example #include <stdio.h> then it knows that printf is the standard library printf (or it could be a macro or maybe static function but then you shouldn’t get the warning).  
> **username_6** (2023-12-19): @gnasher729 I am not sure I understand what point you are trying to make.  
---
### Answer by username_8 on 2023-12-09. Score: 0
The best reason to not raise errors when extra arguments are provided, I think, is to allow the format string to be easily changed ─ or perhaps, provided dynamically ─ without having to change the argument list.
Note that the same is true in other languages such as Python, so this isn't a quirk of C++:
>>> '{} {}'.format('Hello', 'world', 'something')
'Hello world'

The upside is that you can specify the format string elsewhere, or e.g. load it at runtime (useful for internationalisation), and it can be edited without having to edit the code which provides the arguments. For example:
WELCOME_STRING = '{0} version {1}\n\n{3}'

# ...

print(WELCOME_STRING.format(PROGRAM_NAME, PROGRAM_VERSION, COMPILED_DATE, LICENSE_TEXT))

This works even better with keyword-arguments in the format string, although C++ doesn't support those (presumably because libc doesn't):
WELCOME_STRING = '{PROGRAM_NAME} version {PROGRAM_VERSION}\n\n{LICENSE_TEXT}'
> **Comments:**
> **username_9** (2023-12-09): You can't have a dynamic string in C++ though, it has to be known at compile time  
> **username_0** (2023-12-09): Thank you for your answer, but tbh, it makes very weak argument.  
> **username_1** (2023-12-09): @mousetail What do you mean that you can't have a dynamic string in C++? You can get one in all the same ways you can in C, like loading from a file or using a function like `scanf`. `std::string` can be created from a `const char*`.  
> **username_9** (2023-12-09): @Bbrk24 https://ato.pxeger.com/run?1=fVLNTgIxGIzXPsVnvUCARDyZZVkSEw8cfACjZlNLF76k25r-QAjhSbxw8aY-kK_hC7i7XWGTBZr00JnJTOdr37_4m_S23Omc8-8nOrBuNua93s01fdl9eJcNbn8ufq9QcelnAuJMm5y5hBwQ1NYZwfImViCo5m0kXaJYJQQIKgc5Q9Xpkg2BYhWxURREkKGxLlUsF6MWJ1mb4to7iGOg98oJA2vtTfCAUkibSlSQJMcDjrmUaadMzt5kWvfeG0xqh7L4aoF8kYZJtn1PsbV1dQhspymFCdDHqrmXsooEtLAZbi-fFYXon9yPpWBpvzGJ_qFQd0TINrx9_QV2n3f6lTwwI8WaDAP2Bw  
> **username_9** (2023-12-09): What I mean is, in printf/format specifically, the string has to be static.  
> **username_10** (2023-12-09): @mousetail yes with format (at least until C++26 comes out with runtime_format), not with printf: https://godbolt.org/z/zPT8MvWWv  
> **username_8** (2023-12-09): @DeborahC If you're reading my answer as an *argument in favour* of the language being designed this way, then perhaps you misunderstood your own question. You asked for reasons why it would be designed that way, and I gave you what I think is the best reason. I haven't argued that a language *should* be designed any particular way.  
> **username_11** (2023-12-09): The question asks “Why did the C++ language designers make this decision?” This answer does not answer that question; it’s just a guess (and one I don’t think is particularly likely to be the explanation, for what it’s worth).  
---
