为啥这个指针是 8 个字节?

Posted

技术标签:

【中文标题】为啥这个指针是 8 个字节?【英文标题】:Why is this pointer 8 bytes?为什么这个指针是 8 个字节? 【发布时间】:2021-12-28 00:31:50 【问题描述】:

我正在学习 C++,并且读到当一个数组被传递给一个函数时,它会衰减为一个指针。我想玩弄这个并编写了以下函数:

void size_print(int a[])
    cout << sizeof(a)/sizeof(a[0]) << endl;
    cout << "a ->: " << sizeof(a) << endl;
    cout << "a[0] ->" << sizeof(a[0]) << endl;

我试着输入一个包含三个元素的数组,比如说

int test_array[3] = 1, 2, 3;

有了这个输入,我期待这个函数打印 1,因为我认为 a 将是一个整数指针(4 个字节),a[0] 也将是 4 个字节。然而,令我惊讶的是,结果是 2 和 sizeof(a) = 8

我不明白为什么a 占用8 个字节,而a[0] 占用4 个字节。它们不应该是一样的吗?

【问题讨论】:

有趣的事实:a[0] 不是指针,因此不能合理地期望与指针大小相同。 sizeof(a) 是数组传递衰减到的指针的大小。该函数无法知道数组的大小。 @WeatherVane:我认为他们理解这一点(他们清楚地知道它会衰减为指针)。我想他们只是没有意识到 64 位系统有 8 字节指针(很多旧的 C++ 教材仍然假设一切都是 32 位系统)。 @APM500 因为所有指针的大小都相同,无论它们的类型如何。你有一个指向int 的指针。指针为 8 个字节,因为您正在为 64 位系统进行编译。它指向的int 是 4 个字节。 @APM500 整数指针、字符指针、浮点指针或 ifstream 指针没有什么特别之处。所有指针。您的系统上的所有 64 位。 int 告诉您有关指向的内容,而不是指针本身。 【参考方案1】:

他们不应该是一样的吗?

没有。 a 是(应该是)一个数组(但因为它是一个函数参数,已调整为指向第一个元素的指针),因此具有指针的大小。您的机器似乎有 64 位地址,因此,每个地址(因此,每个指针)都是 64 位(8 字节)长。

另一方面,a[0] 是该数组元素所具有的类型(int),并且该类型在您的计算机上具有 32 位(4 个字节)。

【讨论】:

but because it's a function argument, has been decayed to a pointer to the 1st element 这里没有任何衰减,因为这里没有数组。它只是一个指针。 @0___________ 嗯,我不想语言律师,但我不认为typeid(int[])==typeid(int*),对吧? @MarcusMüller 这有点吹毛求疵。衰减是当数组用作操作数时发生的隐式转换。这里发生的是“调整”。参数调整为指针类型。 @ĐăngKhôi 因为我们需要知道它指向什么,所以我们知道如何解释地址中的内容。此外,因为这就是 C++ 的工作原理。 数组类型函数参数是编程语言有史以来最大的谎言之一。它们实际上是指针,即使你提供了一个大小,它也会被忽略而没有任何效果。这种行为在新手经常遇到的数组和指针之间带来了进一步的混淆。数组就是数组。指针是指针。除了函数参数,看起来像数组的是指针。:(.【参考方案2】:

指针只是变量开始所在的内存地址。该地址是 8 个字节。

a[0] 是数组首位的变量。从技术上讲,它可以是任何大小的任何东西。当您使用指向它的指针时,该指针仅包含一个内存地址(整数),而不知道或关心该地址包含什么。 (这只是为了说明这个概念,在问题的示例中,a[] 是一个整数数组,但相同的逻辑适用于任何东西)。

注意,指针的大小实际上在不同的架构上是不同的。这就是 32 位、64 位等的用武之地。它也可以取决于编译器,但这不在问题之列。

【讨论】:

it technically could be anything of whatever size 它在技术上具有非常明确的尺寸 我的意思是存储在数组中的值可以是任何值,以随机数组为例来说明这一点。照原样,它与整数的大小无关。它可以是一个字符,也可以是一个双精度数组或一个嵌套数组。指针不在乎。 没有定义显示指针引用的确切类型 我在问题中添加了解释。该示例可能会混淆对概念的理解。【参考方案3】:

指针的大小取决于系统和实现。您使用 64 位(8 字节)。

a[0] 是一个整数,标准只给出了它必须存储的最小最大值的指示。它可以是 2 个字节以上的任何内容。大多数现代实现使用 32 位(4 字节)整数。

sizeof(a)/sizeof(a[0]) 对函数参数不起作用。数组是通过引用传递的,这个除法只会告诉你指针的大小比整数的大小大多少倍,而不是指针所引用的对象的大小。

【讨论】:

“数组由引用传递”是 C++ 中一个不幸的措辞选择(其中引用与从数组中获得的指针是分开的——>指针衰减)。

以上是关于为啥这个指针是 8 个字节?的主要内容,如果未能解决你的问题,请参考以下文章

CANOpen中一个PDO只能传输8个字节,为啥很多资料都显示一个PDO可以超过8字节?

为什么一个指针在32位系统中占4个字节,在64位系统中占8个字节?

unicode字符集是几个字节表示一个字符?为啥需要utf-8?

为啥数据报很少超过1500字节

c语言,为啥int类型在16位系统中占2个字节,在32位系统中占4个字节?

为啥 gcc 4.x 在调用方法时默认为 linux 上的堆栈保留 8 个字节?