将(指向可变大小数组的指针)强制转换为(指针指向指针)
Casting a (pointer to a variable sized array) to (pointer to pointer)
当我将[指向可变大小数组的指针]转换为[指针指向指针]时,究竟会发生什么?
int ar[r][c];
int **ptr = (int**)ar; // implicit casting not allowed
ptr[0][0] = 100;
以上代码给出一个运行时错误。
将可变大小的数组转换为指针的工作方式与预期一致:
int ar[c];
int *ptr = ar;
ptr[0] = 100;
这里ar
衰变为指向第一个元素的指针。
但是当将int(*)[c]
转换为int**
时内部会发生什么?为什么在读/写int**
变量时导致运行时错误?
数组不是指针。
数组是同一类型数据的连续内存块,所有数据都打包在一起。事实上,如果你有一个指向第一个元素的指针,并且你知道数据的类型,那么你可以用指针做很多可以用数组做的事情。
foo[5]
在数组上得到第5个元素,在指向第一个元素的指针上也得到第5个元素。
实际上,可以将数组转换为foo
类型,隐式地转换为指向第一个元素的指针。
现在,你正在做的是完全不同的事情。指向第一个元素的指针是指向int[5]
(整个数组)的指针。
假设有一个指向int*
的指针数组,长度为5。它们中的每一个都可以指向不同的int[5]
,并且可以将int*[6]
用作二维数组。但是你会注意到这里我们有一个指向int*
的指针数组,而不是指向int[5]
的指针数组。因为数组不是指针,所以它们是不同的东西。
现在,我们可以解决这个问题了
template<unsigned...>struct indexes{typedef indexes type;};
template<unsigned Max, unsigned...Is> struct make_indexes:make_indexes<Max-1, Max-1, Is...>{};
template<unsigned...Is> struct make_indexes<0, Is...>:indexes<Is...>{};
template<unsigned Max> using make_indexes_t = typename make_indexes<Max>::type;
template<typename T, unsigned N, unsigned M, unsigned... Is>
std::array<T*, M> as_array_of_pointers( indexes<Is...>, T(&arr)[M][N] ) {
return { arr[Is]... };
};
template<typename T, unsigned N, unsigned M>
std::array<T*, M> as_array_of_pointers( T(&arr)[M][N] ) {
return as_array_of_pointers( make_indexes_t<M>{}, arr );
}
以上是c++ 11的一种奇特的编写方式:
std::array<int*, 5> arr = { ar[0], ar[1], ar[2] };
现在您可以将ar
转换为指针数组。如果你有一个接受int**
的函数,你可以调用as_array_of_pointers
并接受指向第一个元素的显式指针,并依靠临时生存期来完成工作:
void foo( int** x ) {}
int main() {
int a[5][3] = {0};
foo( &(as_array_of_pointers(a)[0]) );
}
需要c++ 11。您可以在c++ 03中手动执行。
您看到的崩溃(通过未定义的行为)可能是将数组的第一个元素重新解释为指向int
的指针,而不是一个或多个int
(取决于指针和int
在您的系统上的相对大小)的结果。
生活例子
问题是ptr[0]
或*ptr
应该是一个指针,但它不是。也就是说,ptr[0]
或*ptr
不包含有效指针。在这个地址有数组ar的第一个元素。所以当你使用表达式ptr[0][0]
时,你会得到一个运行时错误,这是在一般情况下,程序的行为是未定义的。
声明int **ptr
时,它指向一个int指针数组。但是你声明了一个int型数组的数组。
这就是为什么语言没有为This提供任何隐式强制转换的原因,因为这两种类型实际上并不相关。
像您那样操作强制转换的结果是未定义的行为。
- 正在将指针转换为范围
- 如何理解将半精度指针转换为无符号长指针和相关的内存对齐
- C++:Lambda 函数指针转换的用例是什么?
- 如何将 int 指针转换为浮点指针
- 为什么在将 void 指针转换为整数指针时出现分段错误
- 将(N 个字节)无符号字符指针转换为浮点数和双 C++
- 我们可以在不知道其真实类型的情况下将基类指针转换为派生类指针吗?
- C++中数组大小未知的指针转换
- Antlr cpp 运行时 任何错误的指针转换?
- std::flush可以用于将对象指针转换为其封闭数组指针吗
- C 指针转换会导致内存访问冲突
- 模板类实例化中的指针转换无效
- 函数调用歧义(用户定义的转换和 Derived2Base 指针转换)
- 如何将 void(*)() 类型的指针转换为 void*
- 数组到指针转换期间的临时具体化
- 直接为浮点变量分配十六进制整数与通过指针转换分配之间的区别
- 将基类指针转换为派生的类指针
- 应对 std::字符串中的 std::<char>指针转换后的向量
- 在编译时将函数指针转换为 std::uintptr_t
- 将基类指针转换为未知派生类指针