在哪种情况下,C ++将在编译时检查数组范围? [英] In which case will C++ do array bounds checking at compile time?

查看:142
本文介绍了在哪种情况下,C ++将在编译时检查数组范围?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

受到"使用编译时HTML解析的C ++ HTML模板引擎的想法的启发",我正在尝试编写示例类以检查字符串中的第一个字符是否为a.

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;
}

它运行良好(在Ubuntu上为GCC7.1).如果第一个字符不是a,它将给出编译错误:

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
}

我想知道C ++何时报告超出范围的错误.

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

推荐答案

constexpr要求编译器评估代码.并且,因为在C ++抽象机的上下文中,dummy[1]是未定义的行为,因此它必须发出诊断信息. (这既可以是警告,也可以是错误.但是,g++clang++都选择将其设置为错误.)

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.)

但是,仅仅因为dummy[1]在C ++抽象机的上下文中是未定义的行为,并不意味着其他没有定义该行为.这意味着代码不必一定要被拒绝(如果编译器本身不需要使用它).这只是未定义的行为,不是错误.

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.

例如,编译器编写者将使用无界数组访问,并且由于他们正在编写编译器,因此他们可以确保所发生的行为是所希望的.数组内存管理是一个很好的例子,其中返回的指针通常是在分配的内存开头之后的一个字(因为还需要分配大小.)因此,当编译器编写器需要读取大小时,他或她可能会做的((size_t const*)ptr)[-1].

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].

话虽如此,在这种情况下触发编译器错误的更好方法是简单地使用静态断言:static_assert(p_[0]!='a', "String does not begin with 'a'.").

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'.").

这篇关于在哪种情况下,C ++将在编译时检查数组范围?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆