2

なぜこれが機能するのですか?グローバルデータはコンパイル時に「初期化」されると思います(コンパイラは.globalセクションにobjファイル形式のヌルバイトで保存するため、セクションがメモリにロードされるとヌルに初期化されます)。コンパイラが実行時に関数がメモリ内のどこにあるのか分からない場合、関数アドレスへのポインタをどのように初期化できますか?

#include <iostream>

void vypis();

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

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

}

void vypis() {

}
4

1 に答える 1

4

iostreamソースが実際に C としてコンパイルされるように、の冗長なインクルードを削除し、私のシステムでそれを vypis という実行可能ファイルにコンパイルしました。これが私が見つけたものです:

$ nm vypis | fgrep vypis
00000000004004d0 T vypis
0000000000600888 D vypis_ptr

したがって、vypis関数は「テキスト」セクションのvypis_ptrグローバルであり、関数へのポインタである は「データ」セクションのグローバルです。

データ セクションのオブジェクトの値は実行可能ファイルに格納されておりvypis_ptr、データ セクションをobjdump.

$ objdump -d -j .data vypis

vypis:     file format elf64-x86-64


Disassembly of section .data:

0000000000600878 <__data_start>:
        ...

0000000000600880 <__dso_handle>:
        ...

0000000000600888 <vypis_ptr>:
  600888:       d0 04 40 00 00 00 00 00                             ..@.....

0000000000600890 <bla>:
  600890:       a8 08 60 00 00 00 00 00                             ..`.....

ここで、値4004d0が に格納されていることがわかりますが、これはの出力に表示されているvypis_ptrの場所とまったく同じです。vypisnm

于 2013-03-10T11:21:52.783 に答える