因此,我们正在为Uni进行练习,我们无法弄清楚为什么此代码将第二个值输出为-1 我们认为这是由于16位限制所致,但由于我们不知道其实际含义,因此无法确切了解原因,也无法找到有关此问题的任何资料。对不起,如果这看起来真的很愚蠢,请帮助D:
#include <stdio.h>
#include <stdint.h>
int main() {
int16_t y = 1024, z = 65; // auch "short" als Datentyp verwendbar
y = y * z;
printf("1. Ausgabe: %d\n", y);
printf("2. Ausgabe: %d\n", y / 3 * 3 - 3 * y / 3);
printf("\n");
return 0;
}
我们期望2的结果为0,但输出-1
答案 0 :(得分:1)
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
答案 1 :(得分:0)
int16_t
的范围为[−32768, +32767]
-您在第一次乘法时立即溢出了该范围。
第一个printf打印什么?那应该是一个指示。您还会在问题中提及它。
Google int16_t range
,它将为您显示上述范围。尝试使用int32_t,看看有什么区别。
答案 2 :(得分:0)
给出y = y * z;
,其中所有操作数的类型均为int16_t
,其值为1024 * 65 = 66560,
那么有两种可能性:
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);