将固定数组大小的指针/引用转换为较小的大小是否合法

2024-03-30

根据 C++ 标准,将指针或引用转换为固定数组(例如T(*)[N] or T(&)[N])指向相同类型和 CV 限定的较小固定数组的指针或引用(例如T(*)[M] or T(&)[M])?

基本上,对于所有实例来说,这总是格式良好吗T(无论布局类型如何):

void consume(T(&array)[2]);

void receive(T(&array)[6])
{
  consume(reinterpret_cast<T(&)[2]>(array));   
}

我在以下位置没有看到任何对此有效转换的引用:

  • expr.reinterpret.cast https://timsong-cpp.github.io/cppwp/n3337/expr.reinterpret.cast,
  • expr.static.cast https://timsong-cpp.github.io/cppwp/n3337/expr.static.cast,
  • conv.array https://timsong-cpp.github.io/cppwp/n3337/conv.array, 甚至
  • basic.types https://timsong-cpp.github.io/cppwp/n3337/basic.types

However, it appears that all major compilers accept this and generate proper code even when optimized when using T = std::string (compiler explorer https://gcc.godbolt.org/z/TW7dPW)(not that this proves much, if it is undefined behavior).

据我了解,根据类型系统,这应该是非法的,因为T[2]从未真正创建过,这意味着引用T(&)[2]将无效。


我正在标记这个问题c++11 /questions/tagged/c%2b%2b11因为这是我对答案最感兴趣的版本,但我很想知道这个答案在新版本中是否有所不同。


这里没什么好说的,除了no,在任何语言版本中:类型完全不相关。 C++20 确实允许从T (*)[N] to T (*)[](参考文献也类似),但这并不意味着你可以对待两种不同的Ns 等价。您最接近此规则的“引用”是 [conv.array]/1(“结果是指向数组第一个元素的指针。”,其中T[2]您的示例中不存在)和note在 [defns.undefined] 中(“当本文档省略任何明确的行为定义时,可能会出现未定义的行为”)。

编译器没有“抓住”你的部分原因是这样的reinterpret_casts are有效return到一个又一个对象的真实类型reinterpret_cast用于通过需要指针或对不同类型的引用的接口“偷偷”它(但不use它就是那种类型!)。这意味着给出的代码是合法的,但是明显的定义consume和来电者receive would together导致未定义的行为。 (另一部分是优化器经常不理会代码,那就是always未定义,除非它可以消除分支。)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将固定数组大小的指针/引用转换为较小的大小是否合法 的相关文章

随机推荐