为什么char[]和char*作为typedef不同,但有时.不

Why are char[] and char* as typedefs different, but sometimes... not?

本文关键字:char 不同 作为 为什么 typedef      更新时间:2023-10-16

当我关注这个关于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()?我的怀疑是,由于它们的typedef声明,它们实际上是不同的类型,但为什么变量被报告为相同的类型?

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

无论是直接指定数组类型还是通过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. 当数组表达式是一元&的操作数时(&arr是指向数组的指针,而不是指向指针的指针);以及
  3. 当数组表达式是用于初始化数组类型的对象的字符串文字时(char s[] = "hello";s初始化为数组,而不是指针)

这些情况(或C++中出现的其他情况)都没有出现在您的程序中,所以您的调用:

f2(data,ptr);

将类型为CCD_ 12到CCD_。

f2内部,参数对象xy都属于char*类型,因此std::is_same<decltype(x), decltype(y)>::value为true。

但CCD_ 19和CCD_。ar是不完全数组类型char[],而pr是指针类型char*

它解释了程序的输出。之所以会出现这种奇怪的情况,是因为您使用数组类型ar定义的参数x实际上是char*类型,与pr类型相同。

C族是按值传递的,数组的C值是指向其第一个元素的指针。当你把一个声明为数组的项传递给一个函数时,真正传递的是那个指针,而C把原型当作你这样声明的。

我修改了代码,这样我们就可以看到调用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;
}

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