c++ 将指针转换为指向数组的指针是否被视为UB?[重复]

hts6caw3  于 9个月前  发布在  其他
关注(0)|答案(1)|浏览(154)

此问题在此处已有答案

What is the strict aliasing rule?(11个回答)
Strict aliasing violation and analysis(1个答案)
C++ strict aliasing violation(1个答案)
What is the meaning of unsigned u = (unsigned)&x; in c++ where x is a float variable? [duplicate](3个答案)
11天前关闭
最近我想知道我是否可以显式地定义指针是什么,并显式地确定它的类型。假设我们在表达式auto* x = new int[4];中使用new operator,它返回int*。但是我想保护自己免受可能的错误,并想显式地指示指针中元素的大小。
我发现你可以定义一个指向T(*name)[size]形式的数组的指针。这种类型的指针转换是否被认为是UB?我们似乎通过添加信息来保留基本的指针类型,这是否违反了类型别名的规则?

int main()
{
     auto* p = new int[10];
     decltype(auto) n = (int(*)[10])(p);
     *n[1]=1;
}

字符串

ippsafx7

ippsafx71#

C风格的转换(int(*)[10]) p等价于reinterpret_cast
reinterpret_cast是很难处理的。你正式有UB,其中n是一个类型为“指向int[10]的指针“的指针,但它是指向数组第一个元素的指针(与p相同),而不是数组本身。它们被定义为具有相同的地址,但这并不重要,n不能用于访问数组。
这就是函数std::launder的用武之地:您可以清洗该指针以获得指向实际数组对象的指针,而不是指向其第一个元素。

int main()
{
     using ten_ints = int[10];
     int* p = new ten_ints;
     ten_ints* n = std::launder(reinterpret_cast<ten_ints*>(p));
     (*n)[1]=1;
     assert(p[1] == 1);
}

字符串
但这很难处理,你应该想出替代的解决方案,比如:

int main() {
    {
        using ten_ints = std::array<int, 10>;
        ten_ints* p = new ten_ints;  // Pointer to std::array, doesn't "decay"
    }
    {
        using ten_ints = std::span<int, 10>;
        int* p = new int[10];
        ten_ints s(p, 10);  // Use a span of size 10
    }
}


.当然不是完全使用new,而是使用另一个容器,如std::vector,它可以容纳大小。

相关问题