printf en C n’occupe pas de mémoire?

printf occupe-t-il de la mémoire dans la stack?

 printf("Hello world"); 

"Hello world" a-t-il une adresse constante?

S’il vous plaît aidez-moi à comprendre.

MODIFIER:

Est l’argument que nous passons pour le printf est stocké dans une variable de pointeur local. Si j’utilise un tableau pour stocker une chaîne de 50 chaînes, il faut de la mémoire de stack, mais si j’utilise le printf cela ne prend pas de mémoire. Mais je ne sais pas comment printf ne prend pas la mémoire comme le tableau que nous avons déclaré.

S’il vous plaît aidez-moi à comprendre!

Cela dépend de la convention d’appel de votre plate-forme et de la manière dont la bibliothèque standard est mise en œuvre.

Par exemple, prenez le programme suivant:

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

et la ligne de commande suivante pour le comstackr:

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

Sur une boîte Red Hat 32 bits (i686) utilisant gcc 2.96, nous obtenons le code machine suivant:

       1 fichier "syscall.c"
       2 .version "01.01"
       3 gcc2_comstackd .:
       4 .section .rodata
       5 .LC0:
       6 .ssortingng "Bonjour le monde \ n"
       7 .text
       8 .aligne 4
       9 .globl principal
      10 type principal, @ fonction
      11 principaux:
      12 pushl% ebp
      13 movl% esp,% ebp
      14 sous $ 8,% esp
      15 sous $ 12,% esp
      16 pushl $ .LC0
      17 call printf
      18 addl $ 16,% esp
      19 movl $ 0,% eax
      20 congés
      21 ret
      22 .Lfe1:
      23 taille principale, .Lfe1-main
      24 .ident "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.2 2.96-112.7.2)"

La ligne 16 insère l’adresse du littéral chaîne dans la stack, puis printf est appelé.

Voici le même code, compilé de la même manière, sur une boîte SLES 10 64 bits (x86_64) utilisant gcc 4.1.2:


       1 fichier "syscall.c"
       2 .section .rodata
       3 .LC0:
       4 cordes "Bonjour le monde"
       5 .text
       6 .globl principal
       7 .type main, @function
       8 principaux:
       9 .LFB2:
      10 pushq% rbp
      11 .LCFI0:
      12% de mouvement,% de sharepoint repère
      13 .LCFI1:
      14 movl .LC0,% edi
      15 options de vente
      16 movl $ 0,% eax
      17 congés
      18 ret
 ;;
 ;;  contenu supplémentaire non inclus
 ;;

Dans ce cas, la ligne 14 écrit l’adresse du littéral chaîne dans un registre ( %edi ) au lieu de la pousser dans la stack. Notez également que cette version de gcc est suffisamment intelligente pour se rendre compte que puisque je ne passe qu’un seul argument de type char * , elle peut substituer un appel à puts .

Dans les deux cas, vous créez un nouveau cadre de stack lorsque vous effectuez l’appel. la différence est ce qui est dans le cadre de la stack. Sur la boîte de Red Hat, il inclura l’adresse du littéral chaîne; sur la boîte SLES 10, ce ne sera pas le cas.

Les littéraux de chaîne, qui constituent "Hello world" , occupent de la mémoire, mais pas sur la stack, mais dans un segment statique en lecture seule. Outre la read-only memory , le rest concerne les détails de la mise en œuvre.

Il n’est pas nécessaire que des littéraux de chaîne identiques occupent la même mémoire (il n’est donc pas garanti que l’adresse soit constante), mais ils le pourraient.

En langage C, les littéraux de chaîne ont une durée de stockage statique. Cela signifie qu’ils existent (et que leurs pointeurs restnt valables) pendant toute la durée du programme; C’est l’inverse des variables locales automatiques qui sont généralement implémentées sur une stack de trames d’appel.