sscanf(s,"%u",& v)匹配有符号整数

时间:2017-09-13 11:10:56

标签: c++ scanf sign cppcheck conversion-specifier

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

另见https://ideone.com/OR3IKN

说明符%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;
}

另见https://ideone.com/WPWdqi

结果(S)

令人惊讶的是,在两个转换说明符中都接受以下符号:

value:-4
res:1

我查看了cppreference.com上的文档。对于C(scanf, fscanf, sscanf, scanf_s, fscanf_s, sscanf_s - cppreference.com)以及C ++(std::scanf, std::fscanf, std::sscanf - cppreference.com),"%u"转换说明符的描述是相同的(强调我的):

  

匹配无符号十进制整数。
  数字的格式与strtoul()的预期相同,基本参数的值为10.

观察到的行为标准是否符合要求?我在哪里可以找到这个记录?

[更新]未定义的行为,真的,为什么?

我认为这是simply UB,嗯,加上混淆,这里的版本声明价值为unsigned https://ideone.com/nNBkqN - 我认为-1的分配仍然如预期,但&#34;%u&#34;显然仍符合标志:

#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

2 个答案:

答案 0 :(得分:4)

有两个不同的问题。

  1. %u期望unsigned int*参数;通过int*是UB。
  2. %u是否匹配-4?是。预期的格式是基数为10的strtoul格式,如果您阅读the documentation,则很明显允许使用前导减号。

答案 1 :(得分:3)

不,它不符合标准。实际上,程序的行为是 undefined sscanf的格式说明符必须与参数的类型匹配。