试图理解数组名称的含义
trying to understand what does the name of an array mean
我写了这个简单的程序
#include <iostream>
using namespace std;
int main (){
int arr [5] = {1,2,3,4,5};
cout<<arr<<endl; //Line 1
cout<<&arr<<endl; //Line 2
cout<<sizeof(arr)<<endl; //Line 3
cout<<sizeof(&arr)<<endl; //Line 4
}
我的预期是:
- 第 1 行:
arr
是数组的名称,它是指向第一个元素的指针 arr = &arr[0]
,因此将打印出 &arr[0]
的地址
- 第2行:打印出
arr[0]
的地址,&arr = arr
第 3 行:sizeof(arr)
正在获取 sizof(a pointer)
,因为 arr
是一个指针,我应该获取 4 bytes
第4行:sizeof(&arr)
与第3行相同,因为&arr
是指针类型,所以应该得到4 bytes
但是在第 3 行中:我得到 20 个字节 (sizof(int)* 整数数量)
Line2怎么来的:arr
相当于指针,Line3相当于数组
我知道数组不是指针,但是当传递给函数时它会衰减为指针,sizeof(..)
是一个运算符,因此它将 arr
视为数组,但是<<
也是,它是运算符而不是函数
I know that an array is not a pointer, but when passed to a function it decays to a pointer, sizeof(..) is an operator, and hence it treats arr as an array
没错。因此你在第 2 行得到了 20 个字节。
but so is <<, it is an operator not a function
事实上,当 <<
与除 built-in 整数类型之外的任何东西一起使用时,它是一个 user-defined 函数(请参阅运算符重载)。所以它按预期工作。
要理解 Line2,您确实需要理解数组和指针之间的区别。首先,当你声明一个数组时,你声明了数组持有的类型 (int),然后你保留了组成数组的多个 (int) 大小的字节。毫无疑问,数组是完整的数组结构。
int arr[5] = {1, 2, 3, 4, 5};
如果您想计算出当前机器上 int 的大小(以字节为单位),您可以像在第 4 行中那样询问数组中单个元素的大小。
sizeof &arr
// this is equivalent to ...
sizeof &arr[0]
// you could also ask for just ...
sizeof arr[0]
这些都是 return 你的 4 个字节(你机器上 int 的大小)。
明白一个arr本身是没有地址的。想想当你将一个数组传递给一个函数时,你只是传递了第一个元素的地址。因此这两个函数声明完全相同:
int foo(char *arr);
int foo(char arr[]);
因此,当您在第 3 行中询问数组的大小时,您是在询问整个数组的大小。 (5*4 字节) = 20 字节
另外一个非常重要的理解是,当你将一个数组传递给一个函数时,你传递的只是数组中第一个元素的地址。所以如果你创建了一个函数:
int array_size(char arr[]) { return sizeof arr; }
int main() {
int foo[5] = { 1, 2, 3, 4, 5 };
std::cout << "Foo size: " << array_size(foo) << std::endl;
std::cout << "Foo size: " << sizeof foo << std::endl;
return 0;
}
结果:
Foo size: 4
Foo size: 20
我写了这个简单的程序
#include <iostream>
using namespace std;
int main (){
int arr [5] = {1,2,3,4,5};
cout<<arr<<endl; //Line 1
cout<<&arr<<endl; //Line 2
cout<<sizeof(arr)<<endl; //Line 3
cout<<sizeof(&arr)<<endl; //Line 4
}
我的预期是:
- 第 1 行:
arr
是数组的名称,它是指向第一个元素的指针arr = &arr[0]
,因此将打印出&arr[0]
的地址 - 第2行:打印出
arr[0]
的地址,&arr = arr
第 3 行:
sizeof(arr)
正在获取sizof(a pointer)
,因为arr
是一个指针,我应该获取4 bytes
第4行:
sizeof(&arr)
与第3行相同,因为&arr
是指针类型,所以应该得到4 bytes
但是在第 3 行中:我得到 20 个字节 (sizof(int)* 整数数量)
Line2怎么来的:arr
相当于指针,Line3相当于数组
我知道数组不是指针,但是当传递给函数时它会衰减为指针,sizeof(..)
是一个运算符,因此它将 arr
视为数组,但是<<
也是,它是运算符而不是函数
I know that an array is not a pointer, but when passed to a function it decays to a pointer, sizeof(..) is an operator, and hence it treats arr as an array
没错。因此你在第 2 行得到了 20 个字节。
but so is <<, it is an operator not a function
事实上,当 <<
与除 built-in 整数类型之外的任何东西一起使用时,它是一个 user-defined 函数(请参阅运算符重载)。所以它按预期工作。
要理解 Line2,您确实需要理解数组和指针之间的区别。首先,当你声明一个数组时,你声明了数组持有的类型 (int),然后你保留了组成数组的多个 (int) 大小的字节。毫无疑问,数组是完整的数组结构。
int arr[5] = {1, 2, 3, 4, 5};
如果您想计算出当前机器上 int 的大小(以字节为单位),您可以像在第 4 行中那样询问数组中单个元素的大小。
sizeof &arr
// this is equivalent to ...
sizeof &arr[0]
// you could also ask for just ...
sizeof arr[0]
这些都是 return 你的 4 个字节(你机器上 int 的大小)。
明白一个arr本身是没有地址的。想想当你将一个数组传递给一个函数时,你只是传递了第一个元素的地址。因此这两个函数声明完全相同:
int foo(char *arr);
int foo(char arr[]);
因此,当您在第 3 行中询问数组的大小时,您是在询问整个数组的大小。 (5*4 字节) = 20 字节
另外一个非常重要的理解是,当你将一个数组传递给一个函数时,你传递的只是数组中第一个元素的地址。所以如果你创建了一个函数:
int array_size(char arr[]) { return sizeof arr; }
int main() {
int foo[5] = { 1, 2, 3, 4, 5 };
std::cout << "Foo size: " << array_size(foo) << std::endl;
std::cout << "Foo size: " << sizeof foo << std::endl;
return 0;
}
结果:
Foo size: 4
Foo size: 20