将定点转换为16位到64位?

问题描述 投票:0回答:3

具有最大和最小值的16位数字的定点转换宏:

#define SCALEFACTOR_16(N) ( 1U << N )
#define Q_MAX16 (  SCALEFACTOR_16(16-1) - 1U )
#define Q_MIN16 ( -SCALEFACTOR_16(16-1)      )

将最小值转换为64位:

int64_t x = (int64_t)Q_MIN16;

给出:x == 0x0000 0000 ffff 8000这是一个正数,而不是我的预期。

解决方案是将1U更改为1UL

#define SCALEFACTOR_16(N) ( 1UL << N )

在这种情况下,输出正常:x == 0xffff ffff ffff 8000

为什么第一个案例无法按预期工作?投放期间会发生什么?

c fixed-point
3个回答
1
投票

1U整数常量的类型为unsigned int。移位运算的重排类型是其(提升的)左操作数的重排类型,在这种情况下为unsigned int

虽然对无符号类型执行位移位是正确的方法,但是在完成移位之后,您需要转换回预期的有符号类型。否则,由于编译器会看到无符号类型,因此转换为int64_t不会对数字进行“符号扩展”。

[请注意,由于相同的原因,-SCALEFACTOR_16是可疑的,它实际上不执行任何操作,因为一元减号的操作数是无符号的。从无符号类型正确转换为带符号类型时,编译器将自动处理符号,因此不需要-

[SCALEFACTOR_16也有一个错误,您需要将宏参数包装在括号中。

解决方案:

#define SCALEFACTOR_16(N) ( 1U << (N) )
#define Q_MAX16 ( (int16_t)(SCALEFACTOR_16(16-1) - 1U) )
#define Q_MIN16 ( (int16_t)(SCALEFACTOR_16(16-1)     ) )

您也可以很容易地使该宏非常类型化:

#define SCALEFACTOR(N) ( 1U << (N) )
#define Q_MAX(N) ( (int##N##_t)( SCALEFACTOR(N-1) - 1U ) )
#define Q_MIN(N) ( (int##N##_t)( SCALEFACTOR(N-1)      ) )

完整示例:

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>

#define SCALEFACTOR(N) ( 1U << (N) )
#define Q_MAX(N) ( (int##N##_t)(  SCALEFACTOR(N-1) - 1U ) )
#define Q_MIN(N) ( (int##N##_t)( -SCALEFACTOR(N-1)      ) )

int main (void)
{
  int64_t x;
  x = Q_MIN(16);
  printf("%.16"PRIx64 " %"PRIi64 "\n", x, x);

  x = Q_MIN(32);
  printf("%.16"PRIx64 " %"PRIi64 "\n", x, x);
}

2
投票

您的系统具有32位(unsignedint。您正在执行的所有工作都是使用32位值,并且您将after进行了转换。从unsigned int转换为int64_t时,它不会更改值(它不会将unsigned的高位解释为要扩展的符号位),因此它会填充零。


1
投票

因为您将32位无符号值(0xFFFF 8000)转换为64位有符号值(0x0000 0000 FFFF 8000)。将无符号值转换为较大的类型只会在前面添加0。将带符号的值转换为较大的类型会将符号位添加到前面,例如:

(int64_t)(int32_t)Q_MIN16; ==> 0xffff ffff ffff 8000
© www.soinside.com 2019 - 2024. All rights reserved.