为啥这个指针是 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?