Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to use scanf unsigned int

Tags:

c

scanf

I have the following

 unsigned int value = 12;
 int res = std::sscanf("-567", "%u", &value);

When this is run res is 1 indicating 1 match and value is set to 4294966729 Whereas I was expecting no matches to be made

I would be grateful if someone could explain this behaviour.

like image 537
DourSquid Avatar asked Jan 06 '23 13:01

DourSquid


2 Answers

The C11 Standard states

"... whose format is the same as expected for the subject sequence of the strtoul function with the value 10 for the base argument ..."

and, for strtoul

"... If the subject sequence begins with a minus sign, the value resulting from the conversion is negated ..."

#include <stdio.h>

int main(void) {
    unsigned int value;
    int res;

    res = sscanf("-567", "%u", &value);
    if (res == 1) {
        printf("Value: %u\n", value);
    } else {
        fprintf(stderr, "Error\n");
    }

    res = sscanf("567", "%u", &value);
    if (res == 1) {
        value = ~value + 1; // add 1 in two's complement machines
        printf("Value: %u\n", value);
    } else {
        fprintf(stderr, "Error\n");
    }

    return 0;
}
like image 161
pmg Avatar answered Jan 12 '23 01:01

pmg


Given your usage of std::sscanf(), you're actually using C++, not C. But C++'s sscanf() behaves in largely the same way as in C.

The specification of the %u format specifier allows a sign to be included. Which would essentially mean modulo arithmetic will be employed. Assuming a 32 unsigned int type, the result will be modulo 4294967296 to produce a value between 0 and 4294967295. -567 modulo 4294967296 (aka the smallest positive remainder obtained on dividing -567 by 4294967296) is 4294966729.

like image 31
Peter Avatar answered Jan 12 '23 02:01

Peter