scanf() 中 %u 和 %d 的区别

Difference between %u and %d in scanf()

在 C++ 中,如果我从字符串中读取一个整数,似乎使用 ud 作为转换说明符并不重要,因为它们都接受负整数。

#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;
}

Ideone.com

我深入挖掘以发现是否存在任何差异。我发现

int u, d;
sscanf("-2", "%u", &u);
sscanf("-2", "%d", &d);

相当于

int u, d;
u = strtoul("-2", NULL, 10);
d = strtol("-2", NULL, 10);

根据 cppreference.com.

在使用这些转换说明符进行解析时,ud 之间是否有任何区别,即传递给 scanf 类型函数的格式?这是什么?

C和C++的答案是一样的吧?如果没有,我对两者都感兴趣。

%d:将整数扫描为小数signed int 类似的转换说明符 %i 将前面带有 0x 的数字解释为十六进制,如果前面带有 0,则将其解释为八进制。否则,完全相同。

%u: 将整数扫描为小数 unsigned int.

从技术上讲,当您尝试使用 %u 格式说明符将负数读入 int 时,您正在调用 未定义的行为 。您使 sscanf 将指向有符号整数的指针视为指向无符号整数的指针,并且这些类型不兼容。它之所以有效,是因为无符号整数和有符号整数都具有相似的位表示,而有符号整数使用 2 补码表示。

TL/DR:你不能保证从 sscanf("-2", "%u", &u);

得到 -2

每个 conversion specifier 都有对应的 结果参数类型 在 C 规范中定义。正如您观察到的,%u%d 转换指令实际上 接受相同的输入 ,但是对应于 %u 应为 unsigned int* 类型,而不是 int*。 IE。您的示例应更正为:

unsigned int u;
int d;
sscanf("-2", "%u", &u);
sscanf("-2", "%d", &d);

如果你启用了警告,你会在编译原始示例时得到一个警告。并且 rightfully so:

Unless assignment suppression was indicated by a *, the result of the conversion is placed in the object pointed to by the first argument following the format argument that has not already received a conversion result. If this object does not have an appropriate type, or if the result of the conversion cannot be represented in the object, the behavior is undefined.

强调我的。

因此,您正在调用 undefined behavior(请参阅 未定义行为 部分)。一旦你调用了未定义的行为,你就孤身一人,可能会发生讨厌的事情。


转换修饰符在 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 the std namespace and the minor modifications mentioned in § 27.9.2).

中定义