关于std::span的data()访问越界元素是否合法的技术问询
关于std::span底层指针访问的合法性分析
核心结论
第三个assert(spn.data()[argc] == nullptr);是定义良好的行为,且必定能通过断言。
详细分析
前提:argv的标准规定
根据C/C++标准,argv是一个包含argc+1个元素的数组:
- 前
argc个元素指向命令行参数的字符串; - 第
argc个元素(即argv[argc])被明确要求为nullptr,这个访问是完全合法的。
各个断言的行为对比
第一个断言:
assert(argv[argc] == nullptr);
完全符合标准规定,必定通过,无任何争议。第二个断言:
assert(spn[argc] == nullptr);
属于未定义行为。因为std::span的operator[]有严格前置条件:索引必须落在[0, spn.size())范围内(此处spn.size()等于argc),超出该范围的索引访问会触发未定义行为。第三个断言:
assert(spn.data()[argc] == nullptr);
行为完全合法,原因如下:spn.data()返回指向span底层序列首元素的指针,此处就是argv本身(span由argv和argv+argc构造,底层数据起始地址与argv一致);spn.data()[argc]等价于*(spn.data() + argc),最终等同于argv[argc];- 如前提所述,
argv[argc]是标准保证合法且值为nullptr的操作,因此这个断言必定通过。
关键区分点
span的operator[]是对视图范围的访问,受限于span自身的size();而data()返回的指针是直接指向底层数组的原始指针,只要该指针的操作符合底层数组的合法范围(此处argv的合法索引是0到argc),就不属于未定义行为。
内容的提问来源于stack exchange,提问作者Tootsie
相关产品推荐
相关产品推荐

