1

チェックとして、次のコードを試しました。

const int i = 100;
static int m = 90;
const int p = 40;
int x;

main()
{
    const int j = 40;
    static int k = 40;
    const int n;

    char *p = "Rama";
}

したがって、gccコンパイラで次の出力が得られたので、どの変数がどのセグメントに移動するかを教えてください。私が書いたとき

size ./a.out

私が得た:

text   data   bss    dec   hex   filename
865    268     12   1145   479   ./a.out
4

4 に答える 4

1

変数などは、コンパイラーが配置したい場所に配置されます。コンパイラがオプションを介してどのように動作するかについて、いくつかの選択肢があるかもしれません。

次のリンクにアクセスしてください。

http://en.wikipedia.org/wiki/A.out

http://en.wikipedia.org/wiki/Executable_and_Linkable_Format

于 2010-12-11T13:11:43.757 に答える
1

通常、初期化されていないデータはBSSに送られ、初期化されたデータはDATAに送られます(ここを参照)。

しかし、ISO Cはこの種のことを義務付けていません、それは完全に実装の問題です。decとあなたのhex質問は、それぞれ10進数と16進数で他の3つの合計です。

865 + 268 + 12 = 1145 = 0x479

本当に知りたい場合は、gcc -Sコンパイルしてアセンブリ言語の出力を取得するときやnm、その兄弟がオブジェクトファイルの内部を調べるときなど、さまざまなツールを使用できます。

于 2010-12-11T13:26:41.510 に答える
1

nmを使用できます。次に例を示します。test.cには、投稿した例が含まれています。

gcc -o test test.c
nm -p -m test

00001fb0 (__TEXT,__text) non-external (was a private external) dyld_stub_binding_helper
00001fc4 (__TEXT,__text) non-external (was a private external) __dyld_func_lookup
00002010 (__DATA,__data) non-external dyld__mach_header
00002014 (__DATA,__data) non-external _m
00002018 (__DATA,__data) non-external _k.1510
0000200c (__DATA,__data) external _NXArgc
00002008 (__DATA,__data) external _NXArgv
00002000 (__DATA,__data) external ___progname
00001000 (absolute) [referenced dynamically] external __mh_execute_header
00002004 (__DATA,__data) external _environ
00001ff0 (__TEXT,__literal4) external _i
00001fd2 (__TEXT,__text) external _main
00001ff4 (__TEXT,__literal4) external _p
00002038 (__DATA,__common) external _x
00001f70 (__TEXT,__text) external start
         (undefined [lazy bound]) external _exit (from libSystem)

ここで説明する手法を使用して、変数を移動するセグメントを制御できます。(MS VCではを使用できます#pragme data_seg("segname"))。

于 2010-12-11T13:29:20.560 に答える
0

理論を一度読んだら、あなた(そして私!)はしばしばその意味を忘れてしまうので、あなたはその意味と理解できるものstaticとの間で混乱していると思います。const

1)まず、constconstつまり、この「参照」によって変数の値を変更することはありません。これは、関数の引数、特にポインターを使用する場合に非常に役立ちます。そのため、意図しない値を編集する必要はありません。たとえば、任意に:

void add(int* result, const int* a, const int* b)

この宣言は、誤って入力した場合a = result + b;、コンパイラが文句を言ってコンパイルを拒否する必要があることを意味します。この場合、誤って上書きしないように変数に名前を付けましたが、より複雑なシナリオでは、変数が発生する可能性があります。

ただし、pmgが言うように、これは値が変更されないことを意味するものではありません。それは単に、そのアドレス/値のこのバージョンについて話すとき、それを変更しないことを意味します。ここでの私のポイントは、誤って変更しようとした場合に備えて、変更するつもりのない引数を保護することが役立つということです。真に固定された値が必要な場合は、プリプロセッサがよく使用され#define TRUE 1ます。

2)今static。静的とは、「このコンパイルユニットの外部には表示されない」ことを意味します。これは、クラスのプライベートの概念に似ていますが、同等ではありませんが、この場合は、Cファイル全体について話します。したがって、ファイル内helloworld.cにあり、上部にある場合は、次のように記述します。

static int x = 10;

xその後、そのバージョンのinを使用することはできませんhelloworld2.c

3)私たちがそれに取り組んでいる間、私たちは別の言葉をしたほうがよいでしょうinlineinline私の意見では、マクロを実行するためのより良い方法の一種であり、「コンパイラー、関数呼び出しのコストをかけるのではなく、呼び出した場所にこの結果のコードを実際に配置する必要があります」という意味です。コンパイラの最適化はとにかくこれを行う可能性がありますが、これは可能な場合はインライン化するための明示的な命令として機能します。

要約すると、これらの機能はすべて言語の制御部分であり、実行可能ファイルのさまざまなセグメントのどこに変数が配置されるかではありません。pmg言うように、コンパイラは好きなことを何でもできます。

コンパイラが何をしたかを知りたい場合は、を使用してgcc -Sください。gccこれにより、AT&T形式のアセンブリ言語出力が得られます。最適化がどのように機能するかを理解するために、さまざまなgcc -Oxwhereフラグでこれを試してください。x=0,1,2,3

最後に、実際a.outには単なる名前であることに注意してください。最新のカーネルは、おそらくa.outバイナリをサポートせずにコンパイルされています。

それがあなたが本当に尋ねようとしていた質問だと思います。

于 2010-12-11T13:23:45.663 に答える