sscanf(s, "%u", &v) 匹配有符号整数
sscanf(s, "%u", &v) matching signed integers
在 Cppcheck 抱怨 "%u"
作为扫描到 int
变量的错误格式说明符之后,我将格式更改为 "%d"
,但是当再次查看它时在进行更改之前,我认为其目的可能是为了防止负输入。我写了两个小程序来看看区别:
说明符 %d
#include <iostream>
#include <stdlib.h>
using namespace std;
int main() {
const char* s = "-4";
int value = -1;
int res = sscanf(s, "%d", &value);
cout << "value:" << value << endl;
cout << "res:" << res << endl;
return 0;
}
说明符 %u
#include <iostream>
#include <stdlib.h>
using namespace std;
int main() {
const char* s = "-4";
int value = -1;
int res = sscanf(s, "%u", &value);
cout << "value:" << value << endl;
cout << "res:" << res << endl;
return 0;
}
结果
令人惊讶的是,两个转换说明符都接受符号:
value:-4
res:1
我查看了 cppreference.com 上的文档。对于 C (scanf, fscanf, sscanf, scanf_s, fscanf_s, sscanf_s - cppreference.com) as well as C++ (std::scanf, std::fscanf, std::sscanf - cppreference.com),"%u"
转换说明符的描述是相同的(强调我的):
matches an unsigned decimal integer.
The format of the number is the same as expected by strtoul() with the value 10 for the base argument.
观察到的行为是否符合标准?我在哪里可以找到这个文档?
[更新] 未定义的行为,真的,为什么?
我读到它是 , well, to add to the confusion, here is the version declaring value as unsigned
https://ideone.com/nNBkqN - 我认为 -1
的分配仍然符合预期,但“%u”显然仍然匹配符号:
#include <iostream>
#include <stdlib.h>
using namespace std;
int main() {
const char* s = "-4";
unsigned value = -1;
cout << "value before:" << value << endl;
int res = sscanf(s, "%u", &value);
cout << "value after:" << value << endl;
cout << "res:" << res << endl;
return 0;
}
结果:
value before:4294967295
value after:4294967292
res:1
不,它不符合标准。事实上,您的程序的行为是 undefined:sscanf
的格式说明符必须匹配参数的类型。
有两个不同的问题。
%u
需要一个 unsigned int*
参数;传递一个 int*
是 UB.
%u
匹配 -4
吗?是的。预期格式是以 10 为底的 strtoul
,如果您阅读 the documentation,则很明显允许使用前导减号。
在 Cppcheck 抱怨 "%u"
作为扫描到 int
变量的错误格式说明符之后,我将格式更改为 "%d"
,但是当再次查看它时在进行更改之前,我认为其目的可能是为了防止负输入。我写了两个小程序来看看区别:
说明符 %d
#include <iostream>
#include <stdlib.h>
using namespace std;
int main() {
const char* s = "-4";
int value = -1;
int res = sscanf(s, "%d", &value);
cout << "value:" << value << endl;
cout << "res:" << res << endl;
return 0;
}
说明符 %u
#include <iostream>
#include <stdlib.h>
using namespace std;
int main() {
const char* s = "-4";
int value = -1;
int res = sscanf(s, "%u", &value);
cout << "value:" << value << endl;
cout << "res:" << res << endl;
return 0;
}
结果
令人惊讶的是,两个转换说明符都接受符号:
value:-4
res:1
我查看了 cppreference.com 上的文档。对于 C (scanf, fscanf, sscanf, scanf_s, fscanf_s, sscanf_s - cppreference.com) as well as C++ (std::scanf, std::fscanf, std::sscanf - cppreference.com),"%u"
转换说明符的描述是相同的(强调我的):
matches an unsigned decimal integer.
The format of the number is the same as expected by strtoul() with the value 10 for the base argument.
观察到的行为是否符合标准?我在哪里可以找到这个文档?
[更新] 未定义的行为,真的,为什么?
我读到它是 unsigned
https://ideone.com/nNBkqN - 我认为 -1
的分配仍然符合预期,但“%u”显然仍然匹配符号:
#include <iostream>
#include <stdlib.h>
using namespace std;
int main() {
const char* s = "-4";
unsigned value = -1;
cout << "value before:" << value << endl;
int res = sscanf(s, "%u", &value);
cout << "value after:" << value << endl;
cout << "res:" << res << endl;
return 0;
}
结果:
value before:4294967295
value after:4294967292
res:1
不,它不符合标准。事实上,您的程序的行为是 undefined:sscanf
的格式说明符必须匹配参数的类型。
有两个不同的问题。
%u
需要一个unsigned int*
参数;传递一个int*
是 UB.%u
匹配-4
吗?是的。预期格式是以 10 为底的strtoul
,如果您阅读 the documentation,则很明显允许使用前导减号。