Reputation: 81
I've got a program, which gets numbers n(quantity of blocks) and r(volume), and after it gets n sizes in format firstsize secondsize thirdsize
(e.g. 1 1 1
) so the overall simplest input is:
1 1 1 1 1
which in theory should return 1. But it doesn't.
I have the following code:
#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;
}
Actually, I got this problem solved by changing type of the r
variable in main()
from uint8_t
to int
, but the problem is, I don't understand why it didn't work whilst being uint8_t
. When I try the following code:
cout <<'\n' << static_cast<long long>(static_cast<int>((static_cast<uint8_t>(1))));
It gives me 1.
So, I decided to inspect the situation with uint8_t r
in main()
. uint8_t r = 1
in main()
somehow becomes the int r = 49
in calcMass()
and I do not undertand why.
I know about the rules of implicit conversion, that before the operation variables smaller in size than int
are converted to int
, and then the "smaller in size" variable is converted to bigger one (e.g. int r
to long long
in calcMass(Size,int)
function?), but I do not understand the thing: why do uint8_t r = 1
becomes int r = 49
?
Also, I tried changing the type of r
in calcMass()
from int
to uint8_t
. As supposed, uint8_t r = 1
in main()
becomes uint8_t r = 1
in calcMass()
, but the result of this function is still 49
!
These I used to run the program:
Operating System: Windows 10 Enterprise LTSC
System Type: 64bit
C++ compiler: MinGW
I would be pleased if somebody could explain why explicit conversion of uint8_t
to long long
isn't equal to the imlpicit one when passing it to calcMass()
and doing operations with long long
using it.
Upvotes: 1
Views: 994
Reputation: 20171
IMHO, OP suspected implicit vs. explicit conversion issues but that's not the reason. Instead, the stream
I/O operators have to be investigated.
Elaborating the comment of S.M.:
49 is ASCII code of '1'. So look in the direction of unsigned char to understand why you get 49.
The std::stream
operators work a little bit different for char
, signed char
, and unsigned char
(operator<<(std::basic_ostream), operator>>(std::basic_istream)) than for the other integral types (std::basic_ostream::operator<<, std::basic_istream::operator>>).
That's for input as well as for output.
std::cout << (int)49;
prints 49
but std::cout << (char)49;
prints 1
.
std::uint8_t
is very likely a typedef unsigned char uint8_t;
.
(SO: Implementation of fixed width integer types std::uint8_t and std::int8_t, C++)
Sample:
#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';
}
Output:
(int)49: 49
(char)49: 1
(std::uint8_t)49: 1
i: 49
(int)c: 49
(int)u8: 49
Upvotes: 1