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