Неявное преобразование из uint8_t в int пошло не так, когда явно не прошло - PullRequest
1 голос
/ 02 ноября 2019

У меня есть программа, которая получает числа n (количество блоков) и r (объем), и после этого она получает n размеров в формате firstsize secondsize thirdsize (например, 1 1 1), так что общий простейший ввод: 1 1 1 1 1 который теоретически должен вернуть 1. Но это не так.

У меня есть следующий код:


#include <iostream>
#include <cstdint>
#include <vector>

using namespace std;

struct Size{
    long long w=0,h=0,d=0;
};
istream& operator>>(istream& istr, Size& rval){
    istr >> rval.w >> rval.h >> rval.d;
    return istr;
}


long long calcMass(Size s, int r){
    long long res = s.d*s.h*s.w*r;

    cout << "Gained:" << res << '\n';
    cout << "Got: sizes:{" << s.d << ' ' << s.h << ' ' << s.w << "}, p = " << r << '\n';
    return res;
}


int main(){
    int n;
    long long sum = 0;

    Size s;
    uint8_t r; // Condition is that r<100

    cin >> n >> r;

    for(int i=0; i<n; i++){
        cin >> s;
        sum += calcMass(s,r);
    }
    cout << sum;

}

На самом деле , я решил эту проблему с помощьюизменив тип переменной r в main() с uint8_t на int, но проблема в том, что я не понимаю, почему она не работала, будучи uint8_t. Когда я пробую следующий код:

    cout <<'\n' << static_cast<long long>(static_cast<int>((static_cast<uint8_t>(1))));

Это дает мне 1.

Итак, я решил проверить ситуацию с uint8_t r в main(). uint8_t r = 1 в main() каким-то образом становится int r = 49 в calcMass(), и я не берусь понять почему.

Я знаю о правилах неявного преобразования, которые до операции переменные меньше по размеру, чем int преобразуются в int, а затем переменная "меньшего размера" преобразуется в большую (например, int r в long long в calcMass(Size,int) функции?), но я не понимаю, почему: uint8_t r = 1 становится int r = 49?

Также я попытался изменить тип r в calcMass() с int на uint8_t. Как и предполагалось, uint8_t r = 1 в main() становится uint8_t r = 1 в calcMass(), но результат этой функции по-прежнему 49!

Это я использовал для запуска программы:

Operating System: Windows 10 Enterprise LTSC
System Type: 64bit
C++ compiler: MinGW

Я был бы рад, если бы кто-нибудь смог объяснить , почему явное преобразование uint8_t в long long isn 't равняется unlpicit при передаче его на calcMass() и выполнении операций с long long, используя его.

1 Ответ

1 голос
/ 02 ноября 2019

ИМХО, ОП подозревал проблемы явного и явного преобразования, но это не причина. Вместо этого необходимо исследовать операторы stream.

Разработка комментария для SM :

49 - это код ASCII '1'. Так что посмотрите в сторону беззнакового символа, чтобы понять, почему вы получаете 49.

Операторы std::stream работают немного по-другому для char, signed char и unsigned char ( operator << (std :: basic_ostream) </a>, operator >> (std :: basic_istream) ), чем для других целочисленных типов ( std :: basic_ostream :: operator << </a>, std :: basic_istream :: operator >> ).

Это как для ввода, так и для вывода.

std::cout << (int)49; печатает 49 но std::cout << (char)49; отпечатков 1.

std::uint8_t очень вероятно typedef unsigned char uint8_t;. ( SO: Реализация целочисленных типов фиксированной ширины std :: uint8_t и std :: int8_t, C ++ )

Пример:

#include <iostream>
#include <sstream>
#include <cstdint>

int main()
{
  std::cout << "(int)49: " << (int)49 << "\n";
  std::cout << "(char)49: " << (char)49 << "\n";
  std::cout << "(std::uint8_t)49: " << (std::uint8_t)49 << "\n";
  int i; char c; std::uint8_t u8;
  std::istringstream in("49\n1\n1");
  in >> i >> c >> u8;
  std::cout << "i: " << i << '\n';
  std::cout << "(int)c: " << (int)c << '\n';
  std::cout << "(int)u8: " << (int)u8 << '\n';
}

Вывод:

(int)49: 49
(char)49: 1
(std::uint8_t)49: 1
i: 49
(int)c: 49
(int)u8: 49

Демонстрация в реальном времени на coliru

...