【问题标题】:sscanf(s, "%u", &v) matching signed integerssscanf(s, "%u", &v) 匹配有符号整数
【发布时间】:2018-02-22 01:45:06
【问题描述】:

在 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

结果

令人惊讶的是,两个转换说明符都接受了这个符号:

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() 所期望的格式相同,base 参数的值为 10。

观察到的行为标准是否合规?我在哪里可以找到此文档?

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

我读到它是simply UB,好吧,为了增加混乱,这里是声明值的版本unsignedhttps://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

【问题讨论】:

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


【解决方案1】:

有两个不同的问题。

  1. %u 需要 unsigned int* 参数;传递int* 是UB。
  2. %u 是否匹配 -4?是的。预期的格式是基数为 10 的 strtoul,如果您阅读 the documentation,很明显可以使用前导减号。

【讨论】:

  • 我明白了,我最好一直关注这个链接。我坚持标题“匹配无符号十进制整数”。 (这里有明确的unsigned
【解决方案2】:

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

【讨论】:

  • 所以"%u""%d" 控制是否使用strtoulstrtol
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-12-07
  • 2016-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-11
相关资源
最近更新 更多