【问题标题】:Why are char[] and char* as typedefs different, but sometimes... not?为什么 char[] 和 char* 作为 typedefs 不同,但有时......不是?
【发布时间】:2013-09-05 00:55:28
【问题描述】:

当我关注this question 关于char[]char* 的差异时,出现了以下观察结果。

#include <iostream>

typedef char ar[];
typedef char* pr;
void f2(ar x, pr y)
{
    std::cout << std::is_same<decltype(x), decltype(y)>::value << '\n';
    std::cout << std::is_same<ar, pr>::value << '\n';
}

int main()
{
    char data[] = "data";
    char *ptr = data;
    f2(data,ptr);
    return 0;
}

输出(在 Apple LLVM 版本 4.2 (clang-425.0.28) 上)

1
0

为什么这些报告为不同的类型,而不是不同的 decltype()s ?我怀疑它们实际上是不同的 types,因为它们的 typedef 声明,但为什么变量报告为 same 类型?

【问题讨论】:

  • 腐烂? (作为函数参数)
  • (详细说明我的评论:)函数的参数类型按照 [dcl.fct]/5 进行“衰减”:“确定每个参数的类型后,任何类型为“数组”的参数T”或“函数返回T”分别调整为“指向T”或“指向返回T的函数的指针”。因此decltype(x)指向char 的指针,而不是char 的未知边界数组(与ar 不同)。
  • @DyP 谢谢你的标准参考,先生。
  • @WhozCraig 你可能想检查 std::decay (en.cppreference.com/w/cpp/types/decay)。
  • 愿你问过的唯一问题能带你进入神奇的 20k !我可以第一个祝贺你吗...

标签: c++ decltype


【解决方案1】:

在 C++ 中,与在 C 中一样,声明为数组类型的参数调整(在编译时)为指针类型,特别是指向数组元素类型的指针。 p>

无论是直接指定数组类型还是通过 typedef 指定,都会发生这种情况(请记住,typedef 不会创建新类型,只是现有类型的别名)。

所以这个:

typedef char ar[];
typedef char* pr;
void f2(ar x, pr y)
{
    // ...
}

真正的意思:

void f2(char* x, char* y)
{
    // ...
}

C 和 C++ 共享的另一条规则是,数组类型的 表达式 在大多数但不是所有上下文中,隐式转换为指向数组对象的第一个元素。这意味着如果你定义一个数组对象:

char arr[10];

您可以将该对象的名称用作带有char* 参数(丢失边界信息)的函数的参数。

在 C 中,这种隐式转换不会发生的情况是:

  1. 当数组表达式是sizeof 的操作数时(sizeof arr 产生数组的大小,而不是指针的大小);
  2. 当数组表达式是一元&amp;的操作数时(&amp;arr是指向数组的指针,不是指向指针的指针);和
  3. 当数组表达式是用于初始化数组类型对象的字符串文字时(char s[] = "hello";s 初始化为数组,而不是指针)。

这些情况(或 C++ 中发生的其他情况)都不会出现在您的程序中,因此您的调用:

f2(data,ptr);

char* 类型的两个指针值传递给f2

f2内部,参数对象xy都是char*类型,所以std::is_same&lt;decltype(x), decltype(y)&gt;::value为真。

但是arpr 类型是不同的。 ar是不完整的数组类型char[]pr是指针类型char*

这解释了您的程序的输出。奇怪的发生是因为您使用数组类型ar 定义的参数x 实际上是char* 类型,它与pr 的类型相同。

【讨论】:

  • 谢谢你,基思。这很好地呈现,并且与 Dyp 从一般评论中的标准参考一致,准确地解释了所看到的内容。非常感谢。
【解决方案2】:

C 系列是按值传递的,数组的 C 值是指向其第一个元素的指针。当您将声明为数组的项传递给函数时,真正传递的是该指针,C 将原型视为您以这种方式声明它。

【讨论】:

    【解决方案3】:

    我更改了代码,以便我们可以看到调用 f2 是如何更改类型的。在调用之前,变量具有不同的类型。通话后他们变得一样了

        typedef char ar[];
    typedef char* pr;
    void f2(ar x, pr y)
    {
        cout << is_same<decltype(x), decltype(y)>::value << '\n'; //same type
    }
    
    int main()
    {
        ar data = "data";
        pr ptr = data;
        cout << is_same<decltype(data), decltype(ptr)>::value << '\n'; // different
        f2(data,ptr);
        return 0;
    }
    

    输出是 0 0 .正如@jthill、@Dyp 和@keith Thompson 所说,这是因为数组衰减为指针。

    【讨论】:

    • 该问题的另一个“可视化”:is_same&lt;decltype(x), char[]&gt;is_same&lt;ar, char[]&gt;f2 内(当然还有 is_same&lt;decltype(x), char*&gt;)。
    • 哦,还有一些有趣的事情:is_same&lt;decltype(data), ar&gt; 也是 false(因为 ar 不完整,并且 [basic.types]/6 表示它们是不同的)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-04
    • 2020-05-31
    相关资源
    最近更新 更多