Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;-函数的全局指针_C++_C_Pointers - Fatal编程技术网

C++ C++;-函数的全局指针

C++ C++;-函数的全局指针,c++,c,pointers,C++,C,Pointers,为什么会这样?我认为全局数据在编译时被“初始化”(编译器以obj文件格式null字节保存到.global节,因此当该节加载到内存中时,它被初始化为null)。那个么,若编译器在运行时不知道函数在内存中的位置,那个么如何初始化指向函数地址的指针呢 #include <iostream> void vypis(); int neco; int * bla = &neco; void (*vypis_ptr)() = vypis; int main(int argc, con

为什么会这样?我认为全局数据在编译时被“初始化”(编译器以obj文件格式null字节保存到.global节,因此当该节加载到内存中时,它被初始化为null)。那个么,若编译器在运行时不知道函数在内存中的位置,那个么如何初始化指向函数地址的指针呢

#include <iostream>

void vypis();

int neco;
int * bla = &neco;
void (*vypis_ptr)() = vypis;

int main(int argc, const char * argv[])
{

}

void vypis() {

}
#包括
void vypis();
int neco;
int*bla=&neco;
void(*vypis_ptr)()=vypis;
int main(int argc,const char*argv[]
{
}
void vypis(){
}

我删除了
iostream
的冗余include,因此您的源代码实际上编译为C,并在我的系统上将其编译为一个名为vypis的可执行文件。以下是我的发现:

$nm vypis | fgrep vypis
0000000000 4004D0吨vypis
0000000000 600888 D vypis\u ptr
因此,
vypis
,一个函数,在“文本”部分是一个全局函数,
vypis\u ptr
,一个指向函数的指针,在“数据”部分是一个全局函数

数据部分中的对象具有存储在可执行文件中的值,我可以通过使用
objdump
转储数据部分来读取
vypis_ptr
中的内容

$objdump-d-j.数据vypis
vypis:文件格式elf64-x86-64
分解截面。数据:
0000000000600878 :
...
0000000000600880 :
...
0000000000600888 :
600888:d0 04 40 00….@。。。。。
0000000000600890 :
600890:a8 08 60 00 00。。。。。

在这里,我们可以看到值
4004d0
存储在
vypis_ptr
中,但这正是
vypis
的位置,如
nm
的输出所示
I删除了
iostream
的冗余包含,以便您的源代码实际编译为C,并在我的系统上将其编译为可执行文件叫做vypis。以下是我的发现:

$nm vypis | fgrep vypis
0000000000 4004D0吨vypis
0000000000 600888 D vypis\u ptr
因此,
vypis
,一个函数,在“文本”部分是一个全局函数,
vypis\u ptr
,一个指向函数的指针,在“数据”部分是一个全局函数

数据部分中的对象具有存储在可执行文件中的值,我可以通过使用
objdump
转储数据部分来读取
vypis_ptr
中的内容

$objdump-d-j.数据vypis
vypis:文件格式elf64-x86-64
分解截面。数据:
0000000000600878 :
...
0000000000600880 :
...
0000000000600888 :
600888:d0 04 40 00….@。。。。。
0000000000600890 :
600890:a8 08 60 00 00。。。。。

在这里,我们可以看到值
4004d0
存储在
vypis_ptr
中,但这正是
vypis
的位置,如
nm
的输出所示。您确定编译器正在处理这些问题吗?main中没有任何内容,因此它无需执行任何操作,因此不需要包含任何有问题的代码。@PhilH,当然必须执行,vypis_ptr是一个外部可见的对象。这种地址解析不一定由编译器执行,而是由加载程序执行。唯一重要的事情是在程序启动前完成。而且,至少理论上,C和C++的这些东西是不同的。在C++中,这甚至可以是一个构造函数,它在程序启动后运行,但在它进入代码>主< <代码> >。@ JensGustedt将其作为答案,这是一个重要的部分。info@JensGustedtthx,把它作为答案贴出来,这样我就可以接受了。你确定编译器会为此烦恼吗?main中没有任何内容,因此它无需执行任何操作,因此不需要包含任何有问题的代码。@PhilH,当然必须执行,vypis_ptr是一个外部可见的对象。这种地址解析不一定由编译器执行,而是由加载程序执行。唯一重要的事情是在程序启动前完成。而且,至少理论上,C和C++的这些东西是不同的。在C++中,这甚至可以是一个构造函数,它在程序启动后运行,但在它进入代码>主< <代码> >。@ JensGustedt将其作为答案,这是一个重要的部分。info@JensGustedtthx,将其作为答案发布,所以我可以接受ithm,但为什么obj文件中有我的变量的名称?@Krab,因为它们是全局的,并且您使它们可见(通过没有将它们声明为
static
),所以它们可以导出并在其他编译模块中使用。名称必须在那里,以便链接器可以找到符号。@Krab:
-d
意味着不可禁用,此选项使用符号表中的信息来注释data section.hm输出中的地址。但是为什么obj文件中有my变量的名称?@Krab,因为它们是全局的,并且您使它们可见(通过没有将它们声明为
static
)这样它们就可以被导出并在其他编译模块中使用。名称必须在那里,以便链接器可以找到符号。@Krab:
-d
表示不允许使用,此选项使用符号表中的信息来注释数据段输出中的地址。