1

我正在制作一个游戏(为了好玩),它有一个滚动屏幕。以下代码更新位置:

screen_x += screen_scroll_x;
if(screen_x < 0)
    screen_x = 0;

if(screen_x > map_width - screen_width)
    screen_x = map_width - screen_width;

我正在努力为 screen_x 选择正确的整数类型。如果已签名,则会screen_x > map_width - screen_width引发警告“未签名和已签名之间的比较”。如果它未签名,则if(screen_x < 0)失败(具有创造性结果),因为 screen_x 永远不会是负数。

map_width在加载地图时与字符串的长度进行比较,因此如果我们进行map_width签名,问题就会转移到代码的那部分。

很多人说你应该使用正确的整数。他们还说要注意你的警告,我确实收到警告(警告太多,你不再关注它们),这让我很烦恼。

什么是理想的解决方案?

4

2 回答 2

0

当二元运算符的两侧有不同的符号时,有符号的操作数将被提升为无符号的。这在 C 标准中是一个奇怪的问题,但您必须通过强制转换(但在这种情况下这将是一个错误)或在这种情况下,通过使用有符号整数来保存这两个值来处理它。

于 2012-08-18T11:51:06.263 回答
0

如果您对数学上合理的比较感兴趣,则unsigned不应直接进行任意比较。signed ints那是因为 C(++) 的算术不是你的常规数学算术。

在涉及 asigned int和 an的 C(++) 表达式中unsigned intsigned int首先将 a 转换为 an unsigned int,然后执行操作(+、*、< 等)。

要正确比较 asigned int和 an,unsigned int您应该考虑 C(++) 的“算术规则”以及编程语言强制要求且外行人看不到的类型/值转换。

因此,您可以像这样比较两者:

/* returns -1 if s < u,
   returns 0 if s == u,
   returns 1 if s > u */
int CompareSignedUnsigned(int s, unsigned u)
{
  if (s < 0) return -1; // negative is always smaller than 0 or positive
  if (s < u) return -1; // obvious
  if (s > u) return 1;  // obvious
  return 0; // obvious
}

至于使用正确的整数类型,这是一个很好的建议,但有时一种大小并不适合所有人。屏幕上的坐标就是这样一个区域,在其中对坐标进行签名可能是非常合理的。

想象一下,例如,您想要一个例程在屏幕上渲染一个框,并且您希望能够绘制一个在屏幕上移动的框,从屏幕外部开始(移入其中)并在屏幕外部结束(移出)。

如果您选择这样的 API:

void DrawBox(unsigned x, unsigned y, unsigned width, unsigned height, color c);

当绘制该框的一部分时,当一个部分在屏幕上而另一个不在屏幕上时,此函数的用户将不得不做一些额外的数学运算。这一切都是因为根本没有办法告诉函数原始/未裁剪的盒子真的不在屏幕上。

现在,如果你选择这个:

void DrawBox(int x, int y, unsigned width, unsigned height, color c);

并将额外的裁剪数学移动到函数内部,突然之间,该函数的用户可以编写非常简单的代码。它可能很简单:

for (int x = -100; x < SCREEN_WIDTH + 100, x++)
  DrawBox(x, SCREEN_HEIGHT / 2, 100, 50, GREEN);
于 2012-08-18T12:15:32.900 回答