如果使用无符号整数,通过减1来将基于1的编号移到基于0的编号是否安全?

Kai*_*ged 4 c c++

在我维护的系统中,用户从基于1的索引方案中请求来自集合的元素.值存储在C++/C中基于0的数组中.

如果错误地输入0作为此函数的输入,以下假设代码是否可移植?在将基于1的编号方案转换为基于0的编号方案时,是否有更好的方法来验证用户的输入?

const unsigned int arraySize;
SomeType array[arraySize];    

SomeType GetFromArray( unsigned int oneBasedIndex )
{
  unsigned int zeroBasedIndex = oneBasedIndex - 1;

  //Intent is to check for a valid index.
  if( zeroBasedIndex < arraySize )
  {
    return array[zeroBasedIndex];
  }

  //else... handle the error
}
Run Code Online (Sandbox Code Playgroud)

我的假设是(unsigned int)( 0 - 1 )总是大于arraySize; 这是真的?

正如一些人在下面的答案中建议的那样,另一种方法是检查oneBasedIndex并确保它大于0:

const unsigned int arraySize;
SomeType array[arraySize];    

SomeType GetFromArray( unsigned int oneBasedIndex )
{
  if( oneBasedIndex > 0 && oneBasedIndex <= arraySize )
  {
    return array[oneBasedIndex - 1];
  }

  //else... handle the error
}
Run Code Online (Sandbox Code Playgroud)

Dan*_*her 5

对于无符号类型,0-1是该类型的最大值,因此它始终是>= arraySize.换句话说,是绝对安全的.

  • 在大多数实现中,是的.在所有实施?不可以.无符号下溢允许在标准中引入某种形式的硬件异常. (2认同)
  • 并不是的.如果size_t大于unsigned int,则"wrapped"值可能会在数组中间的某处结束(例如,仍然使用32位`int`s的64位系统). (2认同)

oua*_*uah 5

无符号整数从不在C++和C中溢出.

对于C++语言:

(C++ 11,3.9.1p4)"无符号整数,声明无符号整数,应遵守算术模2n的定律,其中n是整数特定大小的值表示中的位数."46)"

和脚注46):

"46)这意味着无符号算术不会溢出,因为无法用结果无符号整数类型表示的结果以一个大于最大值的数量减去模数,该数值可以由得到的无符号整数类型表示."

对于C语言:

(C11,6.2.5p9)"涉及无符号操作数的计算永远不会溢出,因为无法用结果无符号整数类型表示的结果以一个大于可由结果表示的最大值的数量的模数减少.类型."