使用数组时常见的陷阱:信任类型 - 不安全链接

时间:2013-02-22 03:47:30

标签: c++ c linker

我正在阅读此链接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()
{}

3 个答案:

答案 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风格数组”。答:几乎从不,除非你必须与其他软件接口。