在C语言中,数组名和指针的关系非常紧密,但它们又不是完全等价的,这让很多新手感到困惑。其实数组名本质上不是指针,但在大多数情况下,它会被隐式转换为指向数组首元素的指针。

数组名与指针的基本区别
#include <iostream>
int main()
{
int arr[5] = { 1, 2, 3, 4, 5 };
int* p = arr; // arr 被隐式转换为 &arr[0]
int size1 = sizeof(arr);
int size2 = sizeof(p);
std::cout << "size1=" << size1
<< ", size2=" << size2
<< std::endl;
return 0;
}
在这个例子中arr是一个指向5个INT元素的数组,P是一个INT型的指针。
在这个示例中,大家应该都知道sizeof(arr) 返回整个数组的大小(在我们的示例中是5 * sizeof(int))。
而p是一个指针,所以sizeof(p) 返回的是指针的大小,它在32位程序下是4个字节,而在64位系统下是8个字节。
这应该没什么疑问,是吧?
数组作为函数参数时的行为
我们这里会将有5个元素的数组ARR传给printSize函数。
在MAIN函数中,我们可以肯定sizeof(arr)的大小是5 * sizeof(int)。
但是在printSize中 sizeof(arr)的大小又是多少呢?
咱们看printSize函数的参数指定了arr是含有5个元素的int型数组,可能有人会说那它的大小肯定也是5 * sizeof(int)。
我们运行一下代码来验证一下,可以看到在printSize中sizeof(arr)是4,它只是一个int指针在32位程序下的大小。
这是很容易令新手产生疑惑的,明明在printSize函数中指定arr参数为5个元素的int型数组,为什么实际上它又只是一个指针呢?
这是因为在 C 语言中,当数组作为参数传递给函数时,数组会自动退化为指向其首元素的指针。
即使你写的是 int arr[5],编译器实际上会把它当作 int *arr 来处理。
在我们的示例中,int arr[5] 中的 5 在函数参数列表中是“装饰品”,并不会限制数组大小。
编译器只是把它当作语法糖,方便代码阅读,它表示预期处理的是数组,但不会在编译时保留数组的大小信息。
#include <iostream>
void printSize(int arr[5]) { // 这里的参数并不是数组,而是指针
std::cout << "sizeof(arr) =" << sizeof(arr)
<< std::endl;
}
int main()
{
int arr[5] = { 1, 2, 3, 4, 5 };
std::cout << "sizeof(arr) = " << sizeof(arr)
<< std::endl;
printSize(arr);
return 0;
}
如何在函数中保留数组大小信息
我们可以采用显式传递数组长度的办法。
例如在我们的函数中,可以在函数第二个参数指定了arr数组的大小。
void printArray(int *arr, int size) {
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
int main() { int arr[5] = {1, 2, 3, 4, 5}; printArray(arr, 5); // 需要额外传递数组大小 return 0; }
总结
好了,关于数组和指针。你现在明白了吗?


