2012-06-27 44 views
0

是否printf佔據堆棧存儲器?的printf在C不佔用內存?

printf("Hello world"); 

"Hello world"是否有固定地址?

請幫我理解。

編輯:

是我們傳遞了printf被存儲在本地指針變量的參數。 如果我使用數組來存儲50個字符串文字,它會佔用堆棧內存,但是如果使用了printf,它不會佔用內存 - 這正是我所聽到的。但我不知道怎麼printf沒有考慮內存作爲我們聲明的數組。

請幫我理解!

回答

1

這取決於你的平臺的調用約定和標準庫是如何實現的。

例如,採取以下程序:

#include <stdio.h> 

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

和下面的命令行編譯它:

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

在使用gcc 2.96 32位的Red Hat盒(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 main: 
    12   pushl %ebp 
    13   movl %esp, %ebp 
    14   subl $8, %esp 
    15   subl $12, %esp 
    16   pushl $.LC0 
    17   call printf 
    18   addl $16, %esp 
    19   movl $0, %eax 
    20   leave 
    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

下面是相同的代碼,已編譯的相同的方式,在64位SLES使用gcc 4.1.2 10盒(x86_64的):

 

     1   .file "syscall.c" 
     2   .section  .rodata 
     3 .LC0: 
     4   .string "Hello, World" 
     5   .text 
     6 .globl main 
     7   .type main, @function 
     8 main: 
     9 .LFB2: 
    10   pushq %rbp 
    11 .LCFI0: 
    12   movq %rsp, %rbp 
    13 .LCFI1: 
    14   movl $.LC0, %edi 
    15   call puts 
    16   movl $0, %eax 
    17   leave 
    18   ret 
;; 
;; additional content not included 
;; 

在這種情況下,線14寫入字符串的地址字面到寄存器%edi)代替推送到堆棧上。還要注意,這個版本的gcc足夠聰明地意識到,由於我傳遞了一個類型爲char *的參數,它可以用puts來代替一個調用。

無論哪種情況,您在撥打電話時都會創建一個新的堆棧幀;不同之處在於堆棧幀中的內容。在Red Hat框中,它將包含字符串文字的地址;在SLES 10盒上,它不會。

5

字符串常量,這是什麼"Hello world"是,佔用內存,而不是在棧中,但在一個只讀的靜態部分。除了read-only memory之外,其餘的都是實現細節。

這是沒有必要的是相同的字符串文字佔用相同的內存(所以地址不能保證恆定的),但他們可能。

+1

請注意,雖然字符串不佔用堆棧,但printf是一個函數調用,並會相應地增加堆棧。 –

+1

@WoodrowDouglass我懷疑這一點。 'printf'本身駐留在一個庫中,它也具有靜態持續時間。 –

+1

我並不是說'printf'的代碼在堆棧中,我的意思是'call'指令將返回地址壓入堆棧,因此調用* any * non-inline函數的行爲會增加堆棧。 –

3

在C語言中,字符串具有靜態存儲時間。這意味着它們在整個程序期間的存在(以及指向它們的指針仍然有效)這與通常在調用幀堆棧上實現的自動局部變量相反。