int16_t的范围是−32,768 ... 32,767
y * z = 1024 * 65 = 66560 ,因此将存储为 66560%2 ^ 16 = 1024
因此您仍然有 y = 1024 ,而您的语句 y = y * z 是没用的
y / 3 * 3 =(y / 3)* 3 = 341 * 3 = 1023!= y 因为四舍五入
3 * y / 3 =(3 * y)/ 3 = y ,因为没有取整
减去后得到-1
问题是您正在溢出变量并进行整数除法
使用浮点数代替int16_t
,
int16_t
的范围为[−32768,+32767]
-您在第一次乘法时立即溢出了该范围。
第一个printf打印什么?那应该是一个指示。您还会在问题中提及它。
Google int16_t range
,它将为您显示上述范围。尝试使用int32_t,看看有什么区别。
,
给出y = y * z;
,其中所有操作数的类型均为int16_t
,其值为1024 * 65 = 66560,
那么有两种可能性:
- 如果您的系统是8位或16位,则将具有16位
int
类型。由于操作数已经是16位,并且将出现带符号的整数溢出,从而调用未定义的行为,因此不会进行类型提升。由于16位带符号整数只能存储最多32767个值。
-
如果您的系统是32位,则y
和z
都将隐式提升(请参阅Implicit type promotion rules)以键入int
,然后是32位。乘法的结果为int
类型。值66560非常合适。
然后在分配后将此32位int
转换为int16_t
。该值将不再适合-发生的是实现定义的从有符号32到有符号16的转换。(理论上,您的系统可能会在此处发出信号。)
在实践中,大多数系统只会占用66560 = 10400h并截断MS字节,剩下1024 = 400h。
在任何一种情况下,给定输入值的大小,方程y = y * z;
都是非常可疑的!这被认为是一个错误。您应该改用uint16_t
或int32_t
。
对于y / 3 * 3 - 3 * y / 3
,它将是1024 / 3 * 3 - 3 * 1024 / 3
。所有操作数都是整数,并且乘法算子*
和/
的算子关联度是从左到右。
因此您得到341 * 3 - 3072 / 3
-> 1023 - 1024
= -1
。
作为旁注,您使用了错误的printf
转换说明符。 int16_t
最正确的是:
#include <inttypes.h>
printf("1. Ausgabe: %"PRIi16 "\n",y);
本文链接:https://www.f2er.com/3167347.html