3
#include <iostream> 

int main() {
  int a[] = { 21, 213, 45 };
  static_assert(a[22], "error for a\n");
  return (0);
}

我有一个形状像数组的查找表int,我需要在编译时检查[]运算符的使用是否可能导致超出范围的读取。

我知道 astatic_assert基本上需要两件事:

  • 常量表达式
  • 给定的表达式应返回 abool或可转换/等价于 abool

现在 in g++ 4.8.1aninitializer_list应该是 C++11 中的常量表达式,我不知道我见过多少次这样if写的构造if(arr[N]){...};那么这个断言有什么问题呢?

4

5 回答 5

4

我认为你可以用一点模板魔法概括你想要的东西。

template<typename T,int N> constexpr bool bounds_check(T (&array)[N], int i)
{
    return i < N;
}

在行动中看到它:http: //ideone.com/kj51N0

于 2013-12-10T16:20:01.867 回答
2

超出数组范围的访问是未定义的行为。所以,从字面上看,任何事情都可能发生。

静态断言都是关于编译时失败的。这直到运行时才会被捕获:太晚了。

于 2013-12-10T16:07:59.650 回答
2

a[22]不是一个常量表达式。另外,它没有范围检查,因为对本机数组的访问*(a + 22)被编译器重写。要获得范围检查,您需要构建a一个std::array加号 C++ 库需要启用范围检查,有些人这样做但仅在调试模式下。

如果你这样做了,我认为这里会起作用static_assert(sizeof(a)/sizeof(*a) > 22, "a not large enough")

于 2013-12-10T16:10:28.020 回答
1

我认为你可以使用:

int a[] = { 21, 213, 45 };
static_assert(sizeof(a)/sizeof(a[0]) > 22, "error for a\n");
return (0);

但这是一个非常奇怪的检查。它仅在索引 ( ) 和在编译时已知22的大小时才有效。a

于 2013-12-10T16:11:25.797 回答
1
template<std::size_t Index, typename T, std::size_t N>
T& at( T(&a)[N] ) {
  static_assert( Index < N, "Out of bounds" );
  return a[Index];
}
template<std::size_t Index, typename T, std::size_t N>
T& at( std::array<T,N>& a ) {
  static_assert( Index < N, "Out of bounds" );
  return a[Index];
}
template<std::size_t Index, typename T, std::size_t N>
T const& at( std::array<T,N> const& a ) {
  static_assert( Index < N, "Out of bounds" );
  return a[Index];
}

采用:

int main() {
  int a[] = { 21, 213, 45 };
  int x = at<22>(a); // fails to compile
  return (0);
}
于 2013-12-10T21:09:12.647 回答