简体   繁体   English

将指针变量链接到 C++ 中的数组时,linker 实际上做了什么?

[英]What does the linker actually do when linking a pointer variable to an array in C++?

I have searched a lot for the extern-array-pointer problem but still feeling confused.我已经为 extern-array-pointer 问题进行了很多搜索,但仍然感到困惑。

In the following code:在以下代码中:

// example 1
//1.cpp
int a[]={1,2,3};  //the array a

//main.cpp
extern int*a;  //the pointer a

In main.cpp , when I use printf to print a , it gives me 1 which is the first four bytes of the array a defined in 1.cpp .main.cpp中,当我使用printf打印a时,它给了我1 ,这是1.cpp中定义的数组a的前四个字节。 And printing &a gives me 0x1234 (for example) which is the address of the first element of the array a defined in 1.cpp .并且打印&a给我0x1234 (例如),这是1.cpp中定义的数组a的第一个元素的地址。

It acts like the pointer a was connected with the array a by the address 0x1234 forcibly.它就像指针a被地址0x1234强行连接到数组a一样。 Thus, the value of the pointer a is what located at 0x1234 , which is 1 , since sizeof(int*) == sizeof(int) in 32-bit.因此,指针a的值位于0x1234处,即1 ,因为sizeof(int*) == sizeof(int)在 32 位中。

I have learned that the linker needs the unresolved symbol table and the export symbol table to link declaration to definition.我了解到 linker 需要未解析的符号表和导出符号表来将声明链接到定义。

While compiling 1.cpp , symbol a was added to the export symbole table and while compiling main.cpp , symbol a was added to the unresolved symbol table.在编译1.cpp时,符号a被添加到导出符号表中,而在编译main.cpp时,符号a被添加到未解析的符号表中。 They should be named differently since their type is not the same.它们的名称应该不同,因为它们的类型不同。

In fact the linker could check the types of variable, because:实际上 linker 可以检查变量的类型,因为:

//example 2
//1.cpp
int a[]={1,2,3}

//2.cpp
extern char *a;

throwing a linking error that char *a was unresolved, but they don't mixed forcibly, linker could catch the error.抛出char *a未解决的链接错误,但它们没有强制混合,linker 可以捕获该错误。
In single unit:在单个单元中:

//example 3
int a[] = {1,2,3};
int *ptr = a; 

the compiler convert the a variable to a temporary int * implicitly, but can not do that while in different units.编译器将a变量隐式转换为临时int * ,但在不同的单位中不能这样做。

So why extern a pointer to receive an array is not caught by the linker.那么为什么外部接收数组的指针没有被 linker 捕获。 What does the linker actually do? linker 实际上是做什么的?

Thank you so much!太感谢了!

The C/C++ part can be dealt with immediately: with many implementations, C doesn't mangle any symbols, since they're all supposed to be unique, and lacking overloading for variables C++ doesn't mangle them either. C/C++ 部分可以立即处理:对于许多实现, C不会破坏任何符号,因为它们都应该是唯一的,并且缺少变量 C++ 的重载也不会破坏它们。 (Variable templates are mangled, as are static data members.) This isn't a requirement of the language: formally, you have to use extern "C" for variables, but the standard allows collisions with unannotated global variables, and this happens frequently in practice (and is now a point of backward compatibility ). (变量模板被破坏,static 数据成员也是如此。)这不是语言的要求:正式地,您必须对变量使用extern "C" ,但标准允许与未注释的全局变量发生冲突,这种情况经常发生在实践中(现在是向后兼容的一点)。 The rest is identical for C and C++. rest 与 C 和 C++ 相同。

What typical linkers manage are the addresses of every variable, with no type information except that implicit in the mangled names.典型的链接器管理的是每个变量的地址,除了隐含在错位名称中的信息外,没有任何类型信息。 The address of an array is that of its first element, so your “pointer” ends up being an alias for that element (with the wrong type).数组的地址是其第一个元素的地址,因此您的“指针”最终成为该元素的别名(类型错误)。 (Since this is, as pointed out in the comments, ill-formed, other hilarity can ensue like stores through the pointer not being visible through the array (as accessed via some other pointer).) A different linker implementation could be more helpful, but again backward compatibility forbids it. (因为正如评论中所指出的那样,这是格式错误的,因此可能会发生其他欢闹,例如通过指针存储在数组中不可见(通过其他指针访问)。)不同的 linker 实现可能会更有帮助,但再次向后兼容性禁止它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM