我正在阅读此链接How do I use arrays in C++?,第5节。使用数组时常见的陷阱,其中的示例如下:
// [numbers.cpp]
int numbers[42] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
// [main.cpp]
extern int* numbers;
int main()
{}
由于numbers.cpp中的'numbers'是数组的名称,它通常可以衰减为指针等于'& numbers [0] ',我希望在main.cpp值中'数字'仍然是'& numbers [0]'。但不是!它取而代之的是“数字[0] ”,即“1”。
或者说我是编译器,在'numbers.cpp'中,我将符号'numbers'看作地址指向'1',为什么这个符号变为?
我明白这就是作者所说的“类型 - 不安全链接”。但我不知道为什么编译器 这样做,即使编译器只是引发类型不匹配链接错误对我来说更有意义。
有人可以帮忙解释一下吗?
谢谢,
注释:
我想我的理解是,编译器在下面看作是等价的,以便链接器成功,否则会出现“未解析的外部”错误:
// [numbers.cpp]
int tmp[42] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; //{1,..9} starts at global address 0x1234
int *numbers = &tmp[0]; //numbers == 0x1234
// [main.cpp]
extern int* numbers; //numbers == 0x1234
int main()
{}
真实情况
// [numbers.cpp]
int numbers[42] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; //{1,..9} starts at global address 0x1234
// [main.cpp]
extern int* numbers; //numbers == numbers[0] == 1
int main()
{}
答案 0 :(得分:2)
以下解释方法有助于:
当a
是数组时(即当编译器知道a
的类型是数组类型时),则语法a[i]
被解释为:返回第i个元素数组。
另一方面,当a
是指针(指向数组的第一个元素)时,相同的语法a[i]
被解释为:查找存储在{{{ 1}},添加与i元素对应的字节数,并返回存储在那里的值。
在a
中,它认为main.cpp
是指针(*)并应用相应的操作。也就是说,它会查找存储在numbers
中的值,将其视为地址,添加一定量的字节并返回存储在该地址的值。
(*)这样做是因为numbers
被声明为指针。编译器不知道它确实是一个数组,因为numbers
是与main.cpp
分开编译的(即它是一个单独的翻译单元)。所以它不会将数组衰减成指针 - 它只是假设它已经是一个指针。
答案 1 :(得分:1)
如果数字是数组,例如。数字[],然后你不能改变它指向的内容。目标文件将符号“数字”映射到实际数组{1,2,...}但是如果数字是指针,例如。 *数字,然后您可以更改它指向的内容,并且目标文件将符号“数字”映射到单个指针值(可能本身指向数组的开头,但我们不知道)。 / p>
数组和指针的行为类似,但不是一回事。
答案 2 :(得分:-3)
在C ++中,典型的答案是“使用容器”。对于类似数组的容器,std :: vector通常是你想要的。如果你想要最大的性能,std :: valarray可能是一个更好的选择(当然,如果你使用它就像使用它一样,例如使用gslice)。
更好的文章是“我什么时候才能使用带有C ++的C风格数组”。答:几乎从不,除非你必须与其他软件接口。