In which case will C++ do array bounds checking at compile time?

大城市里の小女人 提交于 2019-12-07 05:09:46

问题


Inspired by the idea of "C++ HTML template engine that uses compile time HTML parsing", I am trying to write a sample class to check whether the first char in a string is a.

int dummy[0];
class Test
{
public:
    constexpr Test(const char *p):p_(p){}
    constexpr void check()const
    {
        if (p_[0]!='a')
            dummy[1]=0;
    }
    const char *p_;
};


constexpr Test operator"" _test(const char *pszText, size_t)
{
  Test t(pszText);
  t.check();
  return t;
}


int main()
{
    //dummy[1] = 0;
    constexpr Test t = "baa"_test;
}

It works well(GCC7.1 on Ubuntu). If the first char is not a, it will give a compile error:

main.cpp:29:24: error: array subscript value ‘1’ is outside the bounds
of array ‘dummy’ of type ‘int [0]’
constexpr Test t = "baa"_test;

What confused me is that if I change the code to:

int main()
{
    dummy[1] = 0; //no compile error anymore
}

I am wondering when C++ reports an array out of bounds error.


回答1:


constexpr requires that the compiler evaluates the code. And, because, in the context of the C++ abstract machine, dummy[1] is undefined behavior, it must emit a diagnostic. (This can be either a warning or an error. However, both g++ and clang++ choose to make this an error.)

However, just because dummy[1] is undefined behavior in the context of the C++ abstract machine, doesn't mean that something else isn't defining the behavior. This means that the code should not necessarily be rejected (if the compiler itself doesn't need to use it). It simply is undefined behavior, not an error.

For instance, compiler writers will use out of bounds array accesses, and because they're writing the compiler, they can ensure that the behavior that occurs is the one desired. A good example is array memory management, where the pointer returned is typically one word past the beginning of the allocated memory (because the size also needs to be allocated.) So when the compiler writer needs to read the size he or she may do ((size_t const*)ptr)[-1].

That being said, a better way to trigger a compiler error in this case is to simply use a static assert: static_assert(p_[0]!='a', "String does not begin with 'a'.").



来源:https://stackoverflow.com/questions/45487308/in-which-case-will-c-do-array-bounds-checking-at-compile-time

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!