Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 一旦一个T的数组退化为指向T的指针,它还能再变成一个T的数组吗?_C++_Arrays_Pointers - Fatal编程技术网

C++ 一旦一个T的数组退化为指向T的指针,它还能再变成一个T的数组吗?

C++ 一旦一个T的数组退化为指向T的指针,它还能再变成一个T的数组吗?,c++,arrays,pointers,C++,Arrays,Pointers,假设我有一个数组: int a[3] = { 1, 2, 3 }; 现在,如果我要检查“a”的类型,在我的机器上,我得到: cout<<typeid(a).name(); // prints 'A3_i' cout我不确定这是否正是您想要的,但是您可以使用类型转换来获取与原始数组具有相同类型的对象。其思想是使用鲜为人知的指向数组的指针和指向数组的引用来恢复信息。例如: char arr[137]; cout << sizeof(arr) << endl;

假设我有一个数组:

int a[3] = { 1, 2, 3 };
现在,如果我要检查“a”的类型,在我的机器上,我得到:

cout<<typeid(a).name(); // prints 'A3_i'

cout我不确定这是否正是您想要的,但是您可以使用类型转换来获取与原始数组具有相同类型的对象。其思想是使用鲜为人知的指向数组的指针和指向数组的引用来恢复信息。例如:

char arr[137];
cout << sizeof(arr) << endl; // Prints 137
cout << sizeof(arr[0]) << endl; // Prints 1
cout << sizeof(&arr[0]) << endl; // Prints 4 (on my system)
cout << sizeof(*&arr[0]) << endl; // Prints 1
cout << sizeof((char (&) [137]) *&arr[0]) << endl; // Prints 137
因此,您可以恢复信息,但很容易将该信息弄错,从而导致您恢复了错误信息的情况


同样,我不确定这是否是您想要的,但它表明您确实可以使用强制转换来获取阵列大小信息。

这不是您问题的完整答案,但我必须提供以下内容-

我认为,一旦数组类型退化为指针,就没有办法返回到数组类型

原始数组类型为T[N],其中N是数组中的元素数。一旦它衰减为指针,大小信息将永久丢失。正如@TemplateTypeDef所示,您可以将指针强制转换回数组类型,但随后他继续证明,通过强制转换,您只是告诉编译器大小,它实际上没有从指针推断信息的方法

要保留原始类型信息,必须通过引用而不是指针传递数组

#include <iostream>
#include <typeinfo>

template<size_t N>
void ByRef( int(&array)[N] )
{
  std::cout << typeid(array).name() << std::endl;
}

void ByPointer( int *array )
{
  std::cout << typeid(array).name() << std::endl;
  std::cout << typeid((int(&)[4])array).name() << std::endl;
  std::cout << typeid((int(&)[42])array).name() << std::endl;
}

int main()
{
  int a[4] = {1,2,3,4};

  ByRef( a );
  ByPointer( a );

  return 0;
}

不知道你在说什么,但一旦你把
&
的任何东西都记下来,你就只有一个地址了。简单的非对象数据结构不包含描述符,因此,给定地址,无法获取任何地址的更多信息。即使是它寻址的事实,比如说,
char
也只通过指针类型传递——如果您强制转换为
void*
,那么该信息将丢失(直到它曾经存在的程度)

我知道指针类型和数组类型是不等价的。我假设数组类型是指针类型中存储的信息的严格超集。这听起来对吗


信息不“存储”在类型中。信息(如果在运行时存在)存储在变量中。在C/C++中,没有针对非对象的动态类型,因此不仅信息不会“存储”在类型中,而且类型信息也不会“存储”在任何地方。类型信息纯粹是一个编译时概念,它在程序中从一个点“流动”到另一个点,纯粹是编译器静态分析的结果。也就是说,这是一部方便的小说。

我会注意到int[3]不是一种类型,尽管int[]是。@Daniel:“3个int的数组”与“int[]”完全不同,“int[3]”似乎是前者的合理缩写。@Daniel R Hicks-
int[3]
是一种类型;它是三个
int
s的数组类型。当您使用语法
int-arr[3]
声明变量时,您正在声明类型为
int[3]
的名为
arr
的变量。这就是为什么声明数组的作用域中的数组名称与指向数组第一个元素的指针的工作方式不同;类型
int[3]
int*
不同。类似:但你不是在告诉演员你想听什么吗?另外,我想让它处理&*a的组合(这会导致类型从数组类型更改为指针类型),而不是组合*&(保持数组类型不变)。@Jimmy-你完全正确-这只是告诉数组它的大小,因此“我不确定你在找什么。”对于
&*a
,你可以使用cast
(T(*)[size])&*a
来告诉数组它的原始大小,顺便说一句。我很确定,一般来说,这是不可能的,一旦数组大小消失,它就消失了,但是在你有关于大小应该是什么的特殊知识的情况下,我认为我所拥有的是正确的。这很好。当我尝试时:cout@Jimmy-该类型转换将指针转换为指向原始数组的指针。然后需要取消对它的引用以返回原始数组:
cout这很有意义。我取“a”,我尊重它,得到一个int,然后我取它的地址,得到一个指向int的指针,然后我把它转换成指向int数组的指针(我必须告诉它大小),然后我取消引用它,得到我的int数组。明亮的因此,如果我使用了“正确”的大小,那么一切看起来都很酷,但是我是否丢失了原始数组类型中包含的任何信息?我相信我理解您的解释。我所谓的“类型信息”只是一个规范,它指导编译器正确地运行。因此数组类型中的“额外信息”只相当于编译时执行的额外检查(即指针类型不一定要进行的编译时验证)?没有运行时类型信息,除非您为多态类启用它,或者,除非首先计算用于实现多态性的内容。然而,编译时类型信息控制的不仅仅是“额外检查”;数组不是指针
intx[3]
,从概念上讲,在堆栈上为3个整数块分配内存,其地址可以根据需要计算(衰减过程)
int*x
,概念上为一个地址在堆栈上分配内存,而不指定它的地址。吉米,我想你已经知道了。在大多数机器上,甚至没有办法判断一组位是指针还是指针,与整数、字符组还是其他东西相比。有一些机器(我相信IBM iSeries是唯一一台仍在生产的机器)是“基于功能的”,能够将指针与其他数据区分开来(此外,还有一些关于所处理的数据类型的运行时线索),但这些机器是明确的例外。
cout<<typeid( (int[3]) &*a).name(); // does not compile
// "error: ISO C++ forbids casting to an array type `int [3]'"
char arr[137];
cout << sizeof(arr) << endl; // Prints 137
cout << sizeof(arr[0]) << endl; // Prints 1
cout << sizeof(&arr[0]) << endl; // Prints 4 (on my system)
cout << sizeof(*&arr[0]) << endl; // Prints 1
cout << sizeof((char (&) [137]) *&arr[0]) << endl; // Prints 137
char arr[137];
cout << sizeof((char (&) [42]) *&arr[0]) << endl; // Prints 42
#include <iostream>
#include <typeinfo>

template<size_t N>
void ByRef( int(&array)[N] )
{
  std::cout << typeid(array).name() << std::endl;
}

void ByPointer( int *array )
{
  std::cout << typeid(array).name() << std::endl;
  std::cout << typeid((int(&)[4])array).name() << std::endl;
  std::cout << typeid((int(&)[42])array).name() << std::endl;
}

int main()
{
  int a[4] = {1,2,3,4};

  ByRef( a );
  ByPointer( a );

  return 0;
}
A4_i
Pi
A4_i
A42_i