После того, как Cppcheck жаловался на "%u"
как неправильный спецификатор формата для сканирования в int
переменная, я изменил формат в "%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
#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 () со значением 10 для базового аргумента.
Соответствует ли стандарт наблюдаемого поведения? Где я могу найти это документально?
Я читал, что это было просто UB, хорошо, чтобы добавить к беспорядку, вот версия, объявляющая значение как 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
Есть два отдельных вопроса.
%u
ожидает unsigned int*
аргумент; прохождение int*
это UB.%u
матч -4
? Да. Ожидаемый формат strtoul
с основанием 10, и если вы читаете документация Совершенно очевидно, что разрешен ведущий знак минус.Нет, это не соответствует стандарту. На самом деле поведение вашей программы не определено: спецификатор формата для sscanf
должен соответствовать типам аргументов.