0

我有一个奇怪的问题。我有一个动态创建的二维数组 Content,它的高度为 _h,宽度为 _w(在我的实现中,行是第一个参数,列是第二个参数,这在上下文中是有意义的)。两个索引可能超出范围,这是设计使然,如果是这样,那么索引将“环绕”数组:

Content[v.iget()%_h][u.iget()%_w];

v 和 u 是我自己班级的对象;它们内部有一个 __int64 值,而 iget() 如下所示:

return value>>precision;

它返回一个通常的 32 位 int。我用 % 按高度或宽度“包装”这个 int 值,显然余数总是 0 <= r < max。所以这个 % 操作还可以防止任何可能的越界情况,但我有时会在这条线上得到访问冲突。当我查看 v 和 u 的值时,它们类似于 -7753978124 - 实际上,在我的上下文中不应该发生负数(所以我还没有寻找导致它的原因),但无论如何,. iget() 应该把它变成一个普通的整数,%_h 或 %_w 应该把它放在边界内,但是我得到了访问冲突。这怎么可能?

4

2 回答 2

2

应该把它变成一个正常的整数

没有。 (-1 % 2) == -1

所以表达式x % max将返回(-max..max)范围内的值。

这是第一个问题。

第二个问题是这样的:

__int64 a = 0xffffffff00000000;
int b = a >> 32;
printf("%d\n", b);

0xffffffff00000000 >> 32is 0xffffffff,它是一个负数-1(对于带符号的 32 位 int,即)。

您可以使用如下表达式来解决此问题:

((x % width) + width)%width

或者您可以使用 if/else 修复索引:

x %= width;
if (x < 0)
    x += width;

或者,您可以使 iget() return unsigned int但这不会正确地环绕所有不是 2 次幂的宽度和高度的负索引。

于 2012-06-01T02:38:25.820 回答
1

为了绝对确保您没有遇到负值,您可以像下面这样实现索引。它也应该比计算模更快,如果你的语句发生在一个紧密的循环中,这将是一个重要的考虑因素。

__int64 v = v.iget();
__int64 u = u.iget();
Content[v < 0 ? 0 : v > _h ? _h : v][u < 0 ? 0 : u > _w ? _w : u];
于 2012-06-01T04:04:14.723 回答