我在C ++中有一些关于(隐式)类型转换的小问题。
1。 float to int
float f = 554344.76;
int x1 = f;
std::cout << x1 << std::endl;
打印554344
(向下舍入或缩小小数位),但在用float f = 5543444.76;
替换它时,会打印5543445
(向上舍入)。为什么它在第一种情况下四舍五入,在第二种情况下四舍五入?除此之外,对于更大的数字,它会产生完全奇怪的结果(例如5543444675.76
变为5543444480
)。为什么呢?
int x1 = f;
和long int x2 = f;
之间的区别是什么?
2。 Long int to float
long int li;
float x3 = li;
std::cout << x3 << std::endl;
练习的解决方案表示值向下舍入并导致大数值的值不正确。如果我尝试long int li = 5435;
,则不会向下舍入。或long int li = 5435.56;
向下舍入的含义是什么?其次,为什么会导致大数字值不正确?我认为long int和float具有相同的位数。
第3。 char加倍
char c = 130;
double x4 = c;
std::cout << x4 << std::endl;
为什么这会导致-126
而char c = 100;
提供正确的值?
4。 int to char
int i = 200;
char x5 = i;
std::cout << x5 << std::endl;
这不打印任何内容(无输出)。为什么?我认为最多255个结果应该是正确的,因为char可以存储最多255个值。
答案 0 :(得分:3)
我认为最多255个结果应该是正确的,因为char可以存储最多255个值。
这是一个不正确的假设。 (Demo)
如果char被签名且8位(1字节),则有潜在的有符号溢出。它的最大值只有127.这将是未定义的行为。
char
是否已签名是依赖于实现的,但通常是。它总是长1个字节,但允许“1字节”依赖于实现,尽管它几乎普遍是8位。
事实上,如果您引用任何ASCII表,在进入“扩展”ASCII之前它只会达到127,在大多数平台上,您需要一个宽字符类型才能显示它。
所以#3和#4中的代码溢出了。
当您尝试char c = 130
:
警告:隐式常量转换溢出
答案 1 :(得分:3)
浮点数通常没有足够的精度来完全表示5543444.76
。您的float
可能会存储值5543455.0
。对int
的强制转换不是舍入发生的地方。从浮点到int
的转换总是截断小数。尝试使用double
代替float
或直接将值分配给int
来说明差异。
许多float
位用于表示符号和指数,它无法准确表示所有值int
的相同大小。同样,这是精度问题,必须丢弃最低有效数字,从而导致看起来像舍入误差的意外结果。考虑科学记数法。您可以使用少量数字表示非常大范围的值,但只跟踪几个小数点。删除不太重要的数字。
char
可能已签名或未签名,具体取决于您的平台。似乎char
在您的平台上签名为8位,这意味着它只能表示-128到127之间的值,显然130超过了该限制。由于未定义有符号整数溢出,因此您的测试用例可能会执行任何操作,包括换行到-126。
char
个变量在传递给std::cout
时不会打印其值。它们打印与该值相关联的字符。见this table。请注意,由于值200
超出了char
在您的平台上可以表示的最大值,因此它可能会执行任何操作,包括尝试显示没有明显表示的字符。
答案 2 :(得分:2)
float只有23位精度。 5543444不适合23位,因此它会四舍五入到最接近的值。
您有未初始化的li
,因此它是未定义的行为。也许您应该编辑问题以显示您想知道的真实代码。
char
经常签名。 130不能表示为签名char
。这可能是未定义的行为(必须检查标准以确定,它可能是实现定义的,或者可能有一些特殊规则),但在PC CPU的实践中,编译器采用130的最低位为130并显示它们进入8位有符号字符,并设置第8位,产生负值。
与上面的3相同:200不适合您的char
签名的8位整数。相反,它最终会设置符号位,从而产生负值。
答案 3 :(得分:2)
距离5,543,444.76最近的IEEE 754 32位浮点数可以表示为5,543,445.0。见this IEEE 754 converter。因此f
等于5543445.0f
,然后在转换为整数时向下舍入为5543445
。
即使在您的特定系统上,float
和long int
可能具有相同的大小,但是一个中的所有值都不能由另一个表示。例如,0.5f
无法表示为long int
。同样,100000002
不能表示为float
:最近的IEEE 754 32位浮点数为100000000.0f
和100000008.0f
。
通常,您需要阅读有关floattng点表示的信息。 Wikipedia是个不错的开始。
char
可能是signed char
或unsigned char
。在(8位)signed char
案例中,{{1}无法表示。发生有符号整数溢出(即UB),最有可能包含-126(注意130 + 126 = 256)。另一方面,100是130
的完全有效值。
在Extended ASCII Table中,200张地图为signed char
。如果您的系统没有处理扩展的ascii(例如,如果它配置了UTF-8),或者如果您没有字体来表示此字符,那么您将看不到输出。如果您使用È
定义为char
的系统,则无论如何都是UB。