从 uint8_t 到 int 的隐式转换出错了,而显式转换正常
Implicit conversion from uint8_t to int gone wrong, when explicit one gone well
我有一个程序,它获取数字 n(块的数量)和 r(体积),然后它获取格式为 firstsize secondsize thirdsize
(例如 1 1 1
)的 n 个大小,所以整体最简单的输入是:
1 1 1 1 1
理论上应该 return 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;
}
实际上,我通过将 main()
中的 r
变量的类型从 uint8_t
更改为 int
解决了这个问题],但问题是,我不明白为什么它在 uint8_t
时不起作用。当我尝试以下代码时:
cout <<'\n' << static_cast<long long>(static_cast<int>((static_cast<uint8_t>(1))));
它给了我 1。
所以,我决定在main()
中用uint8_t r
考察一下情况。 main()
中的 uint8_t r = 1
不知何故变成了 calcMass()
中的 int r = 49
,我不明白为什么。
我知道隐式转换的规则,就是先把比int
小的变量转成int
,再把"smaller in size"转成更大的变量一个(例如 calcMass(Size,int)
函数中的 int r
到 long long
?),但我不明白:为什么 uint8_t r = 1
变成 int r = 49
?
此外,我尝试将 calcMass()
中 r
的类型从 int
更改为 uint8_t
。按照假设,main()
中的uint8_t r = 1
变成了calcMass()
中的uint8_t r = 1
,但是这个函数的结果还是49
!
这些是我用来运行程序的:
Operating System: Windows 10 Enterprise LTSC
System Type: 64bit
C++ compiler: MinGW
如果有人能解释 为什么 uint8_t
到 long long
的显式转换不等于传递给calcMass()
并使用它对 long long
进行操作。
恕我直言,OP 怀疑隐式与显式转换问题,但这不是原因。相反,必须调查 stream
I/O 运算符。
详细说明:
49 is ASCII code of '1'. So look in the direction of unsigned char to understand why you get 49.
std::stream
运算符对于 char
、signed char
和 unsigned char
(operator<<(std::basic_ostream), operator>>(std::basic_istream)) than for the other integral types (std::basic_ostream::operator<<, std::basic_istream::operator>>) 的工作方式略有不同。
这是输入和输出。
std::cout << (int)49;
打印 49
但 std::cout << (char)49;
打印 1
。
std::uint8_t
很可能是 typedef unsigned char uint8_t;
.
(SO: Implementation of fixed width integer types std::uint8_t and 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
我有一个程序,它获取数字 n(块的数量)和 r(体积),然后它获取格式为 firstsize secondsize thirdsize
(例如 1 1 1
)的 n 个大小,所以整体最简单的输入是:
1 1 1 1 1
理论上应该 return 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;
}
实际上,我通过将 main()
中的 r
变量的类型从 uint8_t
更改为 int
解决了这个问题],但问题是,我不明白为什么它在 uint8_t
时不起作用。当我尝试以下代码时:
cout <<'\n' << static_cast<long long>(static_cast<int>((static_cast<uint8_t>(1))));
它给了我 1。
所以,我决定在main()
中用uint8_t r
考察一下情况。 main()
中的 uint8_t r = 1
不知何故变成了 calcMass()
中的 int r = 49
,我不明白为什么。
我知道隐式转换的规则,就是先把比int
小的变量转成int
,再把"smaller in size"转成更大的变量一个(例如 calcMass(Size,int)
函数中的 int r
到 long long
?),但我不明白:为什么 uint8_t r = 1
变成 int r = 49
?
此外,我尝试将 calcMass()
中 r
的类型从 int
更改为 uint8_t
。按照假设,main()
中的uint8_t r = 1
变成了calcMass()
中的uint8_t r = 1
,但是这个函数的结果还是49
!
这些是我用来运行程序的:
Operating System: Windows 10 Enterprise LTSC
System Type: 64bit
C++ compiler: MinGW
如果有人能解释 为什么 uint8_t
到 long long
的显式转换不等于传递给calcMass()
并使用它对 long long
进行操作。
恕我直言,OP 怀疑隐式与显式转换问题,但这不是原因。相反,必须调查 stream
I/O 运算符。
详细说明
49 is ASCII code of '1'. So look in the direction of unsigned char to understand why you get 49.
std::stream
运算符对于 char
、signed char
和 unsigned char
(operator<<(std::basic_ostream), operator>>(std::basic_istream)) than for the other integral types (std::basic_ostream::operator<<, std::basic_istream::operator>>) 的工作方式略有不同。
这是输入和输出。
std::cout << (int)49;
打印 49
但 std::cout << (char)49;
打印 1
。
std::uint8_t
很可能是 typedef unsigned char uint8_t;
.
(SO: Implementation of fixed width integer types std::uint8_t and 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