0

printfスタック内のメモリを占有しますか?

printf("Hello world");

"Hello world"定数アドレスはありますか?

私が理解するのを手伝ってください。

編集:

渡す引数はprintfローカルポインタ変数に格納されていますか。配列を使用して50文字列リテラルを格納する場合、スタックメモリが必要ですが、Iiを使用する場合、printfメモリは必要ありません。これは私が聞いたことです。printfしかし、宣言した配列としてメモリを使用しない方法はわかりません。

私が理解するのを手伝ってください!

4

3 に答える 3

5

文字列リテラル"Hello world"は、メモリを占有しますが、スタック上ではなく、読み取り専用の静的セグメント内にあります。を除いread-only memoryて、残りは実装の詳細です。

同一の文字列リテラルが同じメモリを占有する必要はありませんが(したがって、アドレスが一定であるとは限りません)、占有する可能性があります。

于 2012-06-27T13:02:56.220 に答える
3

C言語では、文字列リテラルの保存期間は静的です。これは、プログラムの全期間にわたってそれらが存在する(そしてそれらへのポインターは有効なままである)ことを意味します。これは、通常、呼び出しフレームスタックに実装される自動ローカル変数の反対です。

于 2012-06-27T13:05:22.693 に答える
1

これは、プラットフォームの呼び出し規約と標準ライブラリの実装方法によって異なります。

たとえば、次のプログラムを考えてみましょう。

#include <stdio.h>

int main(void)
{
  printf("Hello, World\n");
  return 0;
}

そしてそれをコンパイルするための次のコマンドライン:

gcc -S -std=c99 -pedantic -Wall -Werror syscall.c

gcc2.96を使用する32ビットRedHatボックス(i686)では、次のマシンコードを取得します。

      1 .file "syscall.c"
      2 .version "01.01"
      3 gcc2_compiled .:
      4 .section .rodata
      5 .LC0:
      6 .string "Hello、World \ n"
      7.text。
      8 .align 4
      9 .globl main
     10 .type main、@ function
     11メイン:
     12 pushl%ebp
     13 movl%esp、%ebp
     14 subl $ 8、%esp
     15 subl $ 12、%esp
     16 pushl $ .LC0
     17printfを呼び出す
     18 addl $ 16、%esp
     19 movl $ 0、%eax
     20休暇
     21 ret
     22 .Lfe1:
     23 .size main、.Lfe1-main
     24 .ident "GCC:(GNU)2.96 20000731(Red Hat Linux 7.2 2.96-112.7.2)"

16行目は、文字列リテラルのアドレスをスタックにプッシュしてから、printf呼び出されます。

gcc4.1.2を使用した64ビットSLES10ボックス(x86_64)で、同じ方法でコンパイルされた同じコードを次に示します。

      1 .file "syscall.c"
      2 .section .rodata
      3 .LC0:
      4 .string "Hello、World"
      5.text。
      6.globlメイン
      7 .type main、@ function
      8メイン:
      9 .LFB2:
     10 pushq%rbp
     11 .LCFI0:
     12 movq%rsp、%rbp
     13 .LCFI1:
     14 movl $ .LC0、%edi
     15コールプット
     16 movl $ 0、%eax
     17休暇
     18 ret
;;
;; 追加コンテンツは含まれていません
;;

この場合、行14は、文字列リテラルのアドレスをスタックにプッシュするのではなく、レジスタ( )に書き込みます。%ediこのバージョンのgccは、型の単一の引数を渡しているので、へchar *の呼び出しを置き換えることができることを理解するのに十分賢いことにも注意してくださいputs

どちらの場合も、呼び出しを行うときに新しいスタックフレームを作成しています。違いは、スタックフレームの内容です。Red Hatボックスには、文字列リテラルのアドレスが含まれます。SLES 10ボックスでは、そうではありません。

于 2012-06-27T15:11:54.790 に答える