如何判断一个指针是否是指向数组的指针?

时间:2018-07-27 19:02:12

标签: c++ arrays pointers c++17

考虑这个

template <class T>
inline constexpr bool found_to_be_array (T* specimen)
{
    if constexpr (std::is_array_v<T>) {
        return true;
    }
    else {
        return false;
    };
}

问题是,这将在哪种情况下产生可靠的结果?

说明:我无法更改此功能的占用空间。我没有答案,所以让我在这里发表我的发现。考虑一下:

int ia[]{ 1,2,3,4,5,6,7,8,9,0 };
int iam[3][3][3][3][3]{};

// returns false
auto is_array_1 = found_to_be_array(ia);

// returns true
auto is_array_2 = found_to_be_array(iam);

我仍在研究,但是对于多维数组,found_to_be_array有用。

https://godbolt.org/g/ij73Z4

4 个答案:

答案 0 :(得分:6)

没有这种方法行不通。参数specimen已经衰减为指针类型(或者甚至可能一直都是指针)。 std::is_array使用的元编程技术不会以某种方式追溯到调用者。

此外,您正在(无意间)测试T而不是T*-但更改为后者将无效。

答案 1 :(得分:4)

  

如何判断指针是否为数组的指针?

指针具有类型,指示其指向的内容。当它指向数组时,指针的类型就会反映出来,例如:

int arr[2][2] = {{1,2},{3,4}};
auto x = &arr[0];

x的类型为int(*)[2]-指向2个int的数组的指针,在这种情况下为{1,2}。如果将此指针增加1,它将指向2个int的下一个数组,即{3,4}。如果将此指针传递给函数,则T将推导为int[2],结果将为true;

对于一维数组,没有什么不同

int arr[4] = {1,2,3,4};
auto x = &arr;

x类型将是int(*)[4],它也将起作用,并且该函数将返回true

但是,如果您将数组传递给函数而不是指针,从而迫使它衰减到指向其第一个元素的指针,则数组信息会丢失,因为指针现在的类型为int

auto x = arr;

x的类型为int *,它不指向数组,它指向第一个int,即1。如果将其增加一,它将指向下一个int,依此类推。如果这是指向数组的指针,则将其加1时将指向数组末尾的下一个字节。将此指针传递给函数将返回2,因为false类型不是数组。

因此,要回答您的问题,您可以说出该指针是指向数组的指针,因为该信息将以指针类型提供。

int

int iam[3][3][3][3][3]{}; // returns true auto is_array_2 = found_to_be_array(iam); 衰减到指向其第一个元素的指针,基本上,您正在测试iam是否为数组,数组是否正确,因此可以正常工作。

答案 2 :(得分:1)

总是回答也许。是否非空数据指针指向数组元素。

为什么问?
该语言明确允许您将任何对象都视为一个对象数组的单个元素。当您需要序列,想要复制琐碎的对象等时,这真是太好了。

因此,每个指针都是以下之一:

  1. 空指针
  2. 指向数组元素的指针,
  3. 指向数组元素之外的指针,或者
  4. 无效,表示以下其中一项
    1. 野生,表示从未初始化,或者
    2. 晃来晃去,这意味着指向对象的生命已经结束。

虽然您可以区分情况1和2或3,但其余情况则需要分析该程序当前运行的完整历史记录。

答案 3 :(得分:0)

您对无法更改功能的要求很奇怪/不合理。

如果您不能更改函数签名,则无法检测到参数的产生方式(从ptr或数组),因为该信息丢失了。