In C++, if I read an integer from a string, it seems it does not really matter whether I use u
or d
as conversion specifier as both accept even negative integers.
#include <cstdio>
using namespace std;
int main() {
int u, d;
sscanf("-2", "%u", &u);
sscanf("-2", "%d", &d);
puts(u == d ? "u == d" : "u != d");
printf("u: %u %d\n", u, u);
printf("d: %u %d\n", d, d);
return 0;
}
I dug deeper to find if there is any difference. I found that
int u, d;
sscanf("-2", "%u", &u);
sscanf("-2", "%d", &d);
is equivalent to
int u, d;
u = strtoul("-2", NULL, 10);
d = strtol("-2", NULL, 10);
according to cppreference.com.
Is there any difference at all between u
and d
when using these conversion specifiers for parsing, i.e. in format passed to scanf
-type functions? What is it?
The answer is the same for C and C++, right? If not, I am interested in both.
Each conversion specifier has a corresponding type of the result argument defined in the C spec. The
%u
and%d
conversion directives really accept the same inputs, as you observed, but the argument corresponding to%u
shall be of typeunsigned int*
, notint*
. I.e. your example should be corrected as:Had you enabled warnings, you’d get one when compiling the original example. And rightfully so:
Emphasis mine.
So, you were invoking undefined behavior (see the part What is Undefined Behavior). Once you invoke undefined behavior, you’re alone and nasty things may happen.
Conversion modifiers are defined in C99 (latest public draft, N1256; official PDF). The definition is the same as in C11 (latest public draft, N1570; official PDF). The most recent C++ draft (as of 2015-02-10, N4567) linked from the list of C++ standard documents under another question on Stack Overflow takes the definition of
cstdio
header from C99 and does not modify it (apart from placing the functions into thestd
namespace and the minor modifications mentioned in § 27.9.2).