2010-06-04 15 views
4

Celui-ci est probablement très simple, mais je n'arrive pas à le faire fonctionner.C: Défaut de segmentation lors de l'utilisation de printf

Je cet extrait très simple de code:

#include <stdio.h> 
#include <string.h> 

int main(void) 
{ 

    char buf[100]; 
    char *p = buf; 

    strcpy(p, "Test string"); 

    printf("%s\n", *p); 

} 

Ce qui provoque une erreur de segmentation quand je le lance. Sorties GDB:

Program received signal SIGSEGV, Segmentation fault. 
0xb76af3b3 in strlen() from /lib/i686/cmov/libc.so.6 

Mais je ne comprends toujours pas.

Des commentaires seraient appréciés, merci.

+1

Vous pourriez avoir regardé l'avertissement GCC pour avoir une idée du problème: test.c: Dans la fonction 'main': test.c: 12: avertissement: le format '% s' attend le type 'char *', mais l'argument 2 a le type 'int' –

+0

Assez drôle je n'ai pas reçu ce message d'avertissement, si je l'ai fait j'aurais probablement pu sauver tout le monde y compris moi :) – Hamza

+0

Vous pouvez vous assurer d'utiliser l'indicateur de compilation '-Wall' pour être sûr de ne pas manquer les avertissements. – VeeArr

Répondre

11

Lorsque vous écrivez

printf("%s\n", *p); 

la *p sera la valeur à p[0] qui est un personnage. Le printf cherche cependant un tableau de caractères, le provoquant ainsi à segfault. Rappelez-vous qu'en C, les chaînes ne sont que des tableaux de caractères, et que les tableaux sont effectivement des pointeurs vers le premier élément, c'est pourquoi vous n'avez pas besoin de déréférencer.

Pour résoudre ce problème supprimez * pour obtenir:

printf("%s\n", p); 
+0

Bonjour Il-Bhima, merci pour votre explication claire. – Hamza

10

Vous passez un caractère à printf; vous devriez passer le pointeur.

char buf[100]; 
char *p = buf; 

strcpy(p, "Test string"); 

printf("%s\n", p);  // p, not *p 
+0

Ah, oui. Quand je déférence p j'obtiens un char d'où la confusion de printf. Cela vous semble-t-il correct? Merci. – Hamza

+0

+1 Pour être le premier à répondre – neuro

+2

Lorsque vous passez '* p', vous ne passez qu'un seul caractère par valeur. Lorsque vous passez 'p', vous passez un pointeur sur le premier caractère de la chaîne, donc printf peut accéder au reste de la chaîne. – zildjohn01

3

Remplacer

printf("%s\n", *p); 

avec

printf("%s\n", p); 

Lorsque vous utilisez %s, printf vous attend de passer un char*. Vous passez un char à la place.

+0

Salut Eric, merci - ça l'a arrangé bien que je ne comprenne pas pourquoi. Ne devrions-nous pas différer le pointeur pour obtenir le contenu? – Hamza

+0

@Hamza - seulement si vous vouliez imprimer un seul caractère. Si vous voulez imprimer toute la chaîne, vous devez passer le pointeur pour que printf puisse y accéder. Sinon tout ce qu'il a est le caractère que vous lui avez passé (et pas le reste de la chaîne). Cela a plus de sens? –

+0

C'était l'explication que je cherchais, merci beaucoup! C'est fascinant comme il est facile d'oublier les principes après avoir travaillé avec des langages de haut niveau pendant un certain temps :) – Hamza

2

juste passer la chaîne (le pointeur):

printf("%s\n", p); 

Si vous voulez imprimer le premier char, puis:

printf("%c\n", *p); 
+0

Merci pour l'explication AraK. – Hamza

4

Utilisez ceci:

printf("%s\n", p); 

utilisation " p "au lieu de" * p "

+0

Merci pour le correctif user358443 – Hamza

0

% des causes de printf de() à déréférencer * p. Supposons que la chaîne était "Test string". Puis sur ma boîte sparc Solaris: (dans un programme de test) p serait "visé" à l'adresse 0x54657374. La probabilité que cette adresse particulière fasse partie de votre espace de traitement est proche de zéro.

C'est ce qui a provoqué le signal SIGSEGV (segfault).