首页 > 解决方案 > 转换 int 值的问题

问题描述

因此,我尝试遵循以下示例:Fixed Point Arithmetic in C Programming,但出现以下错误left shift count >= width of type

在此处输入图像描述

我确实在stackoverflow上发现其他人有这个问题,但我不明白这个错误?

#include "contiki.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

//Define sizeof - macros
#define SHIFT_AMOUNT 16 // 2^16 = 65536
#define SHIFT_MASK ((1 << SHIFT_AMOUNT) - 1) // 65535 (all LSB set, all MSB clear)

static int price = 500 << SHIFT_AMOUNT;

void calcTest(){
  price += 10 << SHIFT_AMOUNT;
  price *= 3;
  price /= 4; // now our price is ((500 + 10) * 3) / 4 = 382.5
  printf("price integer is %d\n", price >> SHIFT_AMOUNT);
  printf ("price fraction is %d\n", price & SHIFT_MASK);
}

//Defining two processors, one for making the 'knock' and one to listen
PROCESS(data_comp, "data_comp");
AUTOSTART_PROCESSES(&data_comp);

/*---------------------------------------------------------------------------*/


PROCESS_THREAD(data_comp, ev, data)
{
  static struct etimer timer;

  PROCESS_BEGIN();  
  
  /* Setup a periodic timer that expires after 10 seconds. */
  etimer_set(&timer, CLOCK_SECOND * 10);
  
  while(1) {
    calcTest();
     /* Wait for the periodic timer to expire and then restart the timer. */
    PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&timer));
    etimer_reset(&timer);
  }

  PROCESS_END();
}

标签: ccontiki

解决方案


您链接到的问题中的示例是int为 32 位的 C 实现编写的。在您使用的 C 实现中,int类型似乎是 16 位,这对于 16 位移位来说太短了。您将需要调整代码以使用更短的移位或更宽的整数类型。

每个整数类型都有一个宽度,即用于表示它的位数,包括一个符号位(如果类型是有符号的)和值位,但不包括填充位。

错误消息“left shift count >= width of type”表示左移的数量大于或等于您要移动的整数类型的宽度。例如,如果您将一个 16 位数字左移 16 位,则您将所有位移出整数,并且没有剩下任何位。C 标准本质上将此视为溢出:它没有定义行为。所以编译器会警告你。

由于问题中的代码与问题中的错误消息不完全匹配,我们无法确定,但一种可能性是您正在为int类型为 16 位宽的目标进行编译,因此SHIFT_AMOUNT16 位太多了。请注意,int由于符号位以及 C 标准中定义有符号整数的移位方式,移位 an 也是有问题的。移位时通常最好使用无符号类型。

可能的补救措施包括:

  • 检查您的班次金额。对 16 位使用 16int会导致有点极端的定点类型。您可能需要更小的班次量。
  • 使用更大的整数类型,也许long.
  • 使用更宽的类型进行移位并转换回来。例如,如果long是 32 位,您可以定义SHIFT_MASK((int) ((1l << SHIFT_AMOUNT) - 1))
  • 如果SHIFT_AMOUNT已知至少为 1,但不超过 16,则通过使用更短的移位来避免超出类型的宽度,左操作数已经移位了一位:((2 << SHIFT_AMOUNT-1) - 1).
  • 将操作分为两个班次:((1 << SHIFT_AMOUNT/2 << SHIFT_AMOUNT-SHIFT_AMOUNT/2) - 1).

请注意,上述选项不处理签名问题。您需要澄清上下文以获得进一步的建议。


推荐阅读