IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Importance dans l'odre des déclarations ?


Sujet :

C

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 24
    Par défaut Importance dans l'odre des déclarations ?
    Salut tout le monde,
    Je débute en C (avant j'étais sur java), et j'ai un petit soucis:

    Au début de mon programme, si je déclare mes variables comme ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int fin_test = 1000 ;
    int *p ;
    int nb_valeurs = 0 ;
    int valeur ;
    int max = 0;
    int potentiel ;
    int i ;
    alors le programme marche, mais si je mets la déclaration du pointeur p en premier
    exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int *p ;
    int fin_test = 1000 ;
    int nb_valeurs = 0 ;
    int valeur ;
    int max = 0;
    int potentiel ;
    int i ;
    Et bien dans ce cas-là, j'ai un segmentation fault à l'exécution du programme.

    Quelqu'un pourrait-il m'expliquer quel incidence a l'ordre de la déclaration des variables en C SVP ?

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 24
    Par défaut
    Il semblerait que le problème vienne du nombre de déclarations qui suivent la déclaration du pointeur, car si je reprend l'exemple 1 ( qui marche), et que j'ajoute à la fin des déclaration => segmentation fault...

    Quelqu'un aurait-il une explication SVP (pour m'éviter d'avoir des surprises plus tard) ?

  3. #3
    Membre Expert Avatar de KiLVaiDeN
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    2 868
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 2 868
    Par défaut
    Salut,

    quel compilateur utilises-tu et sur quel système ?

    Personnellement, je ne vois pas de raison à ce que la déclaration fasse planter, mis à part un eventuel bug sur les int sur ta plateforme, mais ça m'étonnerait grandement

  4. #4
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Par défaut
    Bonjour,
    Citation Envoyé par laloi
    Il semblerait que le problème vienne du nombre de déclarations qui suivent la déclaration du pointeur,
    je pencherai plutot pour un comportement indéfinie, tu n'essayerai pas d'utiliser un pointeur non initialisé par harsard?
    Est une bonne habitude à prendre.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 24
    Par défaut
    Merci de vous pencher sur mon problème.

    Comme il n'est pas très long (59 lignes bien aéré), je peux poster le programme au complet si vous voulez.

    Pour compiler j'utilise gcc 4.0.0 sur Mandriva LE 2005.

    Pour le bug des int je sais pas, parceque dans mon dernier exemple c'est un char que je déclare en plus et le résultat est le même.

    Et le int *p = NULL; ne corrige pas mon problème (mais si c'est une bonne habitude à prendre je note, merci ).

  6. #6
    Rédacteur/Modérateur
    Avatar de Trap D
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    4 942
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 4 942
    Par défaut
    +1 gege2061
    A tous les coups c'est une mauvaise initialisation, il faudrait voir la suite du code.
    "La haine seule fait des choix" - Koan Zen
    "Il ne faut pas être meilleur que les autres, il faut être meilleur que soi." Albert Jacquard
    "Ceux qui savent où ils ont posé leur parapluie ne sont pas alcooliques." - pgibonne.
    Faites du Prolog, ça vous changera les idées !
    Ma page Prolog
    Mes codes sources commentés

    Mon avatar : La Madeleine à la veilleuse de Georges de La Tour

  7. #7
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 391
    Par défaut
    Je pense que tu devrais poster le programme en effet.
    Ce qui se passe APRÈS les déclarations promet d'être utile pour trouver le bug...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 24
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    #include <stdio.h>
     
    /* Fonction qui calcule le potentiel d'un nombre
    (on fait en boucle le produit des chiffres, jusqu'à trouver un nombre inférierieur à 10,
    le nombre d'étapes pour atteindre ce nombre est le potentiel du nombre).
    */
     
    int fpotentiel(int nombre) {
    	int compteur = 1 ;
    	int temp ;
    	int unites ;
     
    	while (nombre > 9) {
     
    		temp = 1 ;
     
    		while (nombre > 9) {
    			unites = nombre%10 ;
    			temp = temp * unites ;
    			nombre = (nombre-unites)/10 ;
    		}
     
    		temp = temp * nombre ;
    		compteur = compteur + 1 ;
    		nombre = temp ;
    	}
     
     return compteur;
    }
     
    /* Fonction qui donne le ou les nombres inférieurs à 1000 de plus fort potentiel */
     
    main() {
    	int fin_test = 1000 ;
    	int *p ;
    	int nb_valeurs = 0 ;
    	int valeur ;
    	int max = 0;
    	int potentiel ;
    	int i ;
     
    	for ( valeur = 1 ; valeur < fin_test ; valeur++) {
    		potentiel = fpotentiel(valeur) ;
    		if (potentiel > max) {
    			nb_valeurs = 0 ;
    			p[0] = valeur ;
    			max = potentiel ;
    		}
    		else {
    			if (potentiel == max) {
    				nb_valeurs++ ;
    				p[nb_valeurs]=valeur ;
    			}
    		}
    	}
     
    	printf("Nombre(s) < %d de plus fort potentiel (=%d): ",fin_test,max) ;
     
    	for ( i = 0 ; i <= nb_valeurs ; i++) {
    		printf("%d ",p[i]) ;
    	}
     
    	printf("\n") ;
    }

  9. #9
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Par défaut
    Trouvé, j'ai ajouter quelques corrections (cf commentaires) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    #include <stdio.h>
     
    int fpotentiel(int nombre) {
       int compteur = 1 ;
       int temp ;
       int unites ;
     
       while (nombre > 9) {
     
          temp = 1 ;
     
          while (nombre > 9) {
             unites = nombre%10 ;
             temp = temp * unites ;
             nombre = (nombre-unites)/10 ;
          }
     
          temp = temp * nombre ;
          compteur = compteur + 1 ;
          nombre = temp ;
       }
     
     return compteur;
    }
     
    /* En C90, par defaut, le type de retour est int
       mais vaut mieu le preciser */
    int main() {
       int fin_test = 1000 ;
       int *p = NULL ;
       int nb_valeurs = 0 ;
       int valeur ;
       int max = 0;
       int potentiel ;
       int i ;
    /* Inutilisee
       char c; */
     
       for ( valeur = 1 ; valeur < fin_test ; valeur++) {
          potentiel = fpotentiel(valeur) ;
          if (potentiel > max) {
             nb_valeurs = 0 ;
    /* !! Ici !!
    Dereferencement d'un pointeur NULL */
             p[0] = valeur ;
             max = potentiel ;
          }
          else {
             if (potentiel == max) {
                nb_valeurs++ ;
    /* La aussi l'OS ne doit pas apprecier */
                p[nb_valeurs]=valeur ;
             }
          }
       }
     
       printf("Nombre(s) < %d de plus fort potentiel (=%d): ",fin_test,max) ;
     
       for ( i = 0 ; i <= nb_valeurs ; i++) {
          printf("%d ",p[i]) ;
       }
     
       printf("\n") ;
    /* Ton OS a besoin du retour de main */
    return 0;
    }

  10. #10
    Membre Expert Avatar de KiLVaiDeN
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    2 868
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 2 868
    Par défaut
    Tu as besoin d'utiliser malloc je pense.

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 24
    Par défaut
    Merci,
    Effectivement le problème vient de cette histoire de pointeur nul (quand j'initialise mon pointeur à NULL, j'ai segmentation fault même si j'enlève mon char c (qui n'était là que pour créer l'erreur).

    Mais ne connaissant pas le nombre de valeurs que je vais avoir, comment puis-je faire pour que ça marche STP (je veux bien utiliser malloc, mais je ne sais pas quelle taille réserver) ?

  12. #12
    Membre averti
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 24
    Par défaut
    Je vois actuellement 2 solutions (mais si vous avez mieux, je suis 100% preneur):

    1) faire un malloc approximatif, et faire un realloc chaque fois que je dépasse la mémoire réservée

    2) oublier mon système de tableau, calculer le potentiel de tous mes nombres et garder le potentiel max, puis repasser tous les nombres, et afficher ceux dont le potentiel sera égal au potentiel max.

    Quelle solution serait la meilleure SVP (1, 2, ou autre chose...)

  13. #13
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Par défaut
    Citation Envoyé par laloi
    (je veux bien utiliser malloc, mais je ne sais pas quelle taille réserver) ?
    Tu doit bien avoir une valeur maximal du nombre d'éléments que va contenir le tableau
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
       for ( i = 0 ; i <= nb_valeurs ; i++) {
          printf("%d ",p[i]) ;
       }
    nb_valeurs sert à quoi? Ou si tu ne connait pas cette valeur tu peut commencer par alouer une petite zone puis l'agrandir avec realloc

  14. #14
    Membre Expert Avatar de KiLVaiDeN
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    2 868
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 2 868
    Par défaut
    Il va falloir que tu utilises realloc.

    En fait l'idéal est de faire un malloc ( ou un calloc ) sur une taille que tu considères raisonable, et de faire un minimum de realloc, en faisant attention au fait que realloc peut te retourner un autre pointeur, si la zone mémoire a changé.

    Je te conseille de chercher un cours sur malloc/realloc/calloc afin d'être prêt à affronter toute eventualité

  15. #15
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 391
    Par défaut
    Le nombre maximal est connu : Apparemment, il n'y aura jamais plus que fin_test valeurs.
    Après, si tu en as moins, tu peux toujours faire un realloc() à la fin pour libérer la mémoire allouée en trop.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  16. #16
    Membre averti
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 24
    Par défaut
    Merci pour vos conseils.

    En fait je sais utiliser malloc, calloc, et realloc.

    Je suis donc capable de faire ce programme avec les 3 solutions:
    _malloc approximatif + realloc si nécessaire (mais on m'a dit que realloc pouvait se montrer lent)
    _tableau de "fin_test" valeurs (ce qui revient par exemple à réserver 1000 places en mémoire pour en utiliser 20)
    _trouver le potentiel max, puis repasser la liste de nombre et afficher ceux dont potentiel(nombre) = potentiel_max (revient à parcourir 2 fois la liste)

    Sachant que la limite de 1000 nombres peut très bien être augmentée, maintenant ce que je voudrais savoir c'est la solution la plus efficace en C SVP (histoire de prendre de bonnes habitudes).

    PS: Et j'espère bientôt pouvoir poster plus de réponses que de questions

  17. #17
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 391
    Par défaut
    Il est vrai qu'utiliser le realloc() dans la boucle peut être mauvais pour les performances.
    Ce qui est bon à savoir, c'est que même si tu alloues 1000 valeurs pour en utiliser 20, les 980 restantes ne seront gaspillées que pendant le calcul: Tu peux faire un realloc() une fois que tu as le résultat (donc hors de la boucle) pour ne garder que les 20 premières valeurs (puisque tu remplis le tableau de manière séquentielle)

    Une autre solution pourrait être une liste chaînée, mais elle oblige à faire un malloc() à chaque itération (moins gourmant que realloc(), mais lent quand même, me semble-t-il)...

    Pour le comptage des valeurs, c'est une solution possible. Le choix dépend du temps que ça prendra...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  18. #18
    Membre Expert
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Par défaut
    Citation Envoyé par laloi
    Sachant que la limite de 1000 nombres peut très bien être augmentée, maintenant ce que je voudrais savoir c'est la solution la plus efficace en C SVP (histoire de prendre de bonnes habitudes).
    La solution la plus efficace est celle qui minimise le temps de developpement. De nos jours, une heure de programmation coute plus cher que de la memoire (sauf dans des systemes a contrainte forte ou la memoire est une ressource rare, comme en embarque).

    Donc, je commencerais simplement en declarant le tableau p avec une taille fixe "suffisamment grande" (meme vraiment trop grande, peu importe). Le seul test a faire est de s'assurer qu'on ne depasse pas les limites du tableau. Cela permet un developpement rapide et des tests sur le reste de l'algorithme.

    Ensuite, lorsque tout le monde est content, on peut penser a optimiser l'occupation memoire. Mais dans un second temps seulement. En C, la gestion des ressources est rapidement infernale, et il faut s'y prendre avec prudence.

  19. #19
    Membre Expert Avatar de KiLVaiDeN
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    2 868
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 2 868
    Par défaut
    Personnellement, connaissant mon "perfectionnisme", j'aurais opté pour la méthode 3, c'est à dire repérer le nombre d'élements et leurs tailles d'abord, puis reserver la bonne taille mémoire.
    En fonction de l'endroit où tu récupères tes données, tu devrais avoir un moyen simple d'obtenir le nombre de résultat, que ce soit un COUNT en SQL, ou un simple test sur la taille du fichier, pour bien optimiser ton programme il faudrait que ta source de données soit déjà formattée sous une forme qui permette un traitement efficace, il me semble que c'est encore plus important car après tes traitements en C peuvent vraiment être optimisés.

    Je ne suis pas forcément d'accord sur la suggestion de se moquer de la taille mémoire : certes s'affranchir d'un problème d'optimisation en simplifiant un algorithme écourte le temps de developpement, mais à mon avis miser sur la rapidité de developpement apporte "au final" plus d'ennuis que d'agréments, surtout pour une partie aussi critique que la gestion des données; je suis d'accord que pour des parties moins critiques on fasse l'impasse sur des options d'optimisation "facultatives", mais quand il s'agit du coeur du programme, de la partie qui sera le plus souvent utilisée, il convient d'employer les meilleures méthodes afin d'obtenir au final un produit concurrentiel et efficace.

    Et je dirais même encore une fois, avec mon coté "perfectionniste", un logiciel qui est voué à un franc succès ne saurait être "fait à la va-vite", donc passer un peu de temps pour optimiser peut à la fois être instructif et positif pour le futur du logiciel

    En parlant d'autre chose, il y a encore plus important que la performance : la modularité ! Concevoir un logiciel en se souciant de la réutilisation du code et de l'emploi de bonnes pratiques de programmation ( je pense tout particulièrement à la notion d'objet, que j'affectionne, ainsi que les design patterns ) s'avère être un plus énorme quand au final le logiciel devra évoluer, voir être réécrit !

    Bon courage après ce long discours

  20. #20
    Membre Expert
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Par défaut
    Je suis d'accord dans l'ensemble, mais il ne faut pas faire les choses a l'envers. Je prefere voir un algorithme qui fonctionne en utilisant trois fois trop de memoire qu'un developpeur, debutant en C, completement decourage par la difficulte de gerer les ressources dans ce langage. On commence par faire simple (allocation automatique de la memoire, dans notre cas), ensuite on fait complique (allocation et re-allocation dynamiques). Toujours.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 3
    Dernier message: 13/02/2013, 16h05
  2. (Débutant!) Importer dans C# des données Excel
    Par Bouyou1983 dans le forum C#
    Réponses: 4
    Dernier message: 16/12/2007, 13h23
  3. Importance de l'ordre des champs dans un Group by ?
    Par Noren dans le forum Langage SQL
    Réponses: 1
    Dernier message: 15/12/2007, 13h31
  4. Réponses: 2
    Dernier message: 04/08/2007, 19h26

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo