C语言 int32_t to int64_t (or to float)



我有一个用C编写的非常简单的算法,它从int16_t数组中获取值,将这些值乘以它们的位置并存储到int32_t数组中。还有另一个类型为 int64_t 的变量sum用于存储结果_slops数组中所有值的总和。这是代码。

#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
// these variables initialized separately
int16_t *from;
int32_t *_slops;
int32_t _overlapSize;
...
// main algorithm
int32_t pos;
int64_t sum = 0;
for(pos = 0; pos < _overlapSize; pos++) {
    _slops[pos] = (from[pos] * pos * (_overlapSize - pos));
    sum += (int64_t) _slops[pos];
    if (pos == 2) {
        LOGD("1 ---: %d", (from[pos] * pos * (_overlapSize - pos)));
        LOGD("2 ---: %d", _slops[pos]);
        LOGD("3 sum: %d", sum);
    }
}
LOGD("sum: %d", sum);

当我运行代码时,我看到生成的_slops数组中具有正确的值,但sum变量始终具有相同的值。

02-26 15:58:10.762: D/player(17466): 1 ---: 1154560
02-26 15:58:10.762: D/player(17466): 2 ---: 1154560
02-26 15:58:10.762: D/player(17466): 3 sum: 1504780888
02-26 15:58:10.762: D/player(17466): sum: 1504780904
02-26 15:58:10.840: D/player(17466): 1 ---: 890560
02-26 15:58:10.840: D/player(17466): 2 ---: 890560
02-26 15:58:10.848: D/player(17466): 3 sum: 1504780888
02-26 15:58:10.848: D/player(17466): sum: 1504780904
02-26 15:58:10.848: D/player(17466): 1 ---: 1791680
02-26 15:58:10.848: D/player(17466): 2 ---: 1791680
02-26 15:58:10.848: D/player(17466): 3 sum: 1504780888
02-26 15:58:10.848: D/player(17466): sum: 1504780904

我试图将sum类型更改为float,但结果保持不变。我很确定我在类型转换方面做错了什么(int32_tint64_tint32_tfloat ),但我无法找到正确的方法。

在 C 语言中执行此操作的正确方法是什么?一般来说,如果我将两个int16_t值相乘,得到更大的结果(假设int32_t),我该怎么做?任何帮助都非常感谢。

除非int64_t是计算机上int的别名,否则您使用了错误的printf格式指令。试试这个:

LOGD("sum: %" PRId64, sum);

PRId64 是在 <inttypes.h> 中定义的宏。

如果您使用的是 GCC,则使用 -Wformat 进行编译会生成有关格式不匹配的错误。 -Wall将包括-Wformat,以及许多其他有用的警告。

对于您的第二个问题(关于如何扩大使用窄类型参数的二进制算术运算的结果),这是通过使至少一个操作数达到您想要的宽度来完成的。这可以通过石膏完成:

int16_t a = A_VAL;
int16_t b = B_VAL;
int32_t c = a + (int32_t)b;

如 maverik 的答案所示,在分配给 _slops[pos] 的表达式中,有符号整数溢出的可能性。如果 _overlapSize 大于 29,则 pos * (_overlapSize - pos) 的最大乘积大于 216,这意味着其对 from[pos] 的乘积可能大于 231

这是问题所在:

_slops[pos] = (from[pos] * pos * (_overlapSize - pos));

_slops[pos]是一种int32_t。表达式(from[pos] * pos * (_overlapSize - pos))在某些情况下不能存储在int32_t中,因为from[pos] int16_t乘以int32_tpos,结果可能大于int32_t(考虑2^15 int16_t的最大值和2^31 int32_t的最大值)。 2^15 * 2^31 = 2^46 如果不截断就无法存储为 int32_t

但是你把它写回_slops[pos]这是int32_t.在这一行中:

sum += (int64_t) _slops[pos];

石膏是无用的,不能防止缩小。我建议_slops类型更改为int64_t *或使用临时变量来计算结果:

int64_t tmp = ((int64_t) from[pos] * pos * (_overlapSize - pos));

我不知道pos能有多大,但从这个意义上说,整体表达并不安全。

相关内容

最新更新