c++iostreamcstdint

Surprising result when reading int_fast8_t from std::cin


I am trying to build a simple cpp code to check whether an input number is an even number bigger than 2 (trying to experimentally solve codeforce's watermelon using cstdint). Problem is, when i use int_fast8_t as the data type for the input interger, the code somehow prints "yes" when i put in 2 as an input. This problem is nonexistent when I use basic int data type. Any ideas on why this happens?

the code is as below:

#include <cstdint>
#include <iostream>

int main(int argc, char* argv[]) {
    int_fast8_t input;
    std::cin >> input;

    if ((input % 2 == 0) && (input > 2)) {
        std::cout << "YES";
    } else {
        std::cout << "NO";
    } std::cout << "\n";

    return 0;
}
input: 2

expected output: NO
actual output  : YES

Solution

  • The problem is that int_fast8_t is defined as a type alias for signed char. This isn't required by the C++ standard, but it's what your standard library chose to do.

    You could verify this by looking at the source code of your standard library, or with:

    static_assert(std::is_same_v<std::int_fast8_t, signed char>>);
    

    As a result, what you're actually doing is:

    signed char input;
    std::cin >> input;
    

    This calls operator>>(std::istream&, signed char&), which is a special overload that treats signed char like a character, instead of an integer.

    When providing 2 as user input, this is actually the ASCII/UTF-8 character '2', which has the numeric value 50.

    This passes the test input % 2 == 0 because 50 is divisible by 2, and also passes the test input > 2 because 50 is greater than 2.

    Solution

    To fix this, use int instead; at least for user input.

    See Also