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 :

Pourquoi ma fonction accepte t-elle des int alors qu'elle est declarée pour accepter des bytes ?


Sujet :

C

  1. #1
    Débutant  
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    3 096
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 096
    Points : 944
    Points
    944
    Par défaut Pourquoi ma fonction accepte t-elle des int alors qu'elle est declarée pour accepter des bytes ?
    Bonjour,

    Excusez moi pour mon chinois .

    J'ai un fonction comme ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    void WritePhoneNum(byte posi, char * number){ ...code...}
    donc quand je l'appel
    WritePhoneNum(posi, number);
    posi doit etre un byte et number doit etre un char.

    Je ne comprends pas pourquoi quans je fais ceci ca fonction comme meme
    à savoir que param est un char. Ci-dessous, je le transfomr en int

    Sachez avant que sms_text et param sont des char qui sont déclarés plus haut dans mon code
    char sms_text[20];
    char param[3];
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    WritePhoneNum(atoi(param), sms_text);
    Aussi j'ai d'abord fait un truc de encore plus chinois, mais qui marche
    Je converti param en int puis en byte
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    WritePhoneNum((byte)(atoi(param)), sms_text);
    J'ai donc deux question:
    Pourquoi un int peut "remplacer un byte, comme dans le premier exemple.
    Si c'est bien, ca me va très très bien.

    Pourriez-vous me faire un commentaire sur ceci, en revanche. C'est pas du charbias qui fonctionne?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    WritePhoneNum((byte)(atoi(param)), sms_text);

    Aussi, j'aimerais bien vous poser une autre question.

    Si j'ai un char message[120] qui a pris une valeur de 119 caractere.

    Comment puis bien vider ce char pour gagner de la memoire.

    Es-ce que ceci suffit:
    Qu'es-ce que ca fait exactement. A mon interpretation, il met le caravtere \0 en premiere position qui veut dire fin du string. Donc elle est vide.
    Es-ce juste? Bon je ne donnerai pas un cours avec cette explication, mais ....
    Merci
    Il ne suffit pas de tout savoir. Vouloir et persévérer, c'est déjà presque tout!

  2. #2
    Membre confirmé
    Avatar de deletme
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2011
    Messages : 257
    Points : 519
    Points
    519
    Par défaut
    Bonjour,

    Tu n'as aucun warning de la part de ton compilateur ? ça me semble très bizarre quand même qu'il ne te prévienne pas.

    La page man atoi : http://www.bigbiz.com/cgi-bin/manpage?atoi

    Param doit être de type char* et non char. Pareil pour ta fonction WritePhoneNumber où number doit être un char*

    Alors oui peut être que ta fonction accepte les paramètres, mais je ne parierai pas sur son bon fonctionnement.

    Quant à la libération de mémoire, regarde plutôt comment allouer un tableau de façon dynamique ce qui te permettras de le redimensionner pour gagner l'octet non utilisé (malloc, realloc, free).

    Cdlt, dM
    "Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live."
    - Martin Golding
    Traduction obligatoire : "Toujours écrire du code en gardant en tête que le mec qui en assurera la maintenance est un psychopathe violent qui connait votre adresse"

  3. #3
    Débutant  
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    3 096
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 096
    Points : 944
    Points
    944
    Par défaut
    He non, ca marche bien!! et pas de message dans mon compilateur, mais ta réflexion me préoccupe, car j'aimerais faire un truc de propre

    ça me semble très bizarre quand même qu'il ne te prévienne pas.
    Mais que doit-il me dire?

    Je vais aller voir du cote de malloc
    Il ne suffit pas de tout savoir. Vouloir et persévérer, c'est déjà presque tout!

  4. #4
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void WritePhoneNum(byte posi, char * number){ ...code...}
    number doit etre un char.

    Sachez avant que sms_text et param sont des char qui sont déclarés plus haut dans mon code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char sms_text[20];
    char param[3];
    Tu n'as toujours pas compris la différence entre char et chaine de caractères ou je me trompe ?

    Le reste relève de la bidouille et est non explicable tant qu'on ne connaîtra pas la définition du type byte. Peux-tu aussi nous indiquer ton compilateur, les options de warning activés, l'IDE utilisé (ou la ligne de commande le cas échéant).


    Si j'ai un char message[120] qui a pris une valeur de 119 caractere.
    Comment puis bien vider ce char pour gagner de la memoire.
    Tu ne peux pas. Un tel tableau est une variable locale à la fonction où elle est déclarée et sera détruite uniquement quand on quittera cette fonction. Tu ne pourras pas gagner de mémoire, comme tu ne pourras pas l'agrandir.

    Au passage, essaye de respecter la règle "une question = une discussion". Ainsi, les réponses seront séparées et cela assurera une meilleure lisibilité des réponses.

  5. #5
    Débutant  
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    3 096
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 096
    Points : 944
    Points
    944
    Par défaut
    Tu n'as toujours pas compris la différence entre char et chaine de caractères ou je me trompe ?
    Ben je doute de moi, mais j'ai envie de répondre oui.
    Un tring est une chaine de caractere
    un char est une chaine de caractere qui se présente sous un tableau
    char titi[9]={ 'B', 'o', 'n', 'j', 'o', 'u', 'r', '\0' }
    Peux-tu aussi nous indiquer ton compilateur, les options de warning activés
    Pour ceci je ne sais pas quoi te répondre. J'utilise l'IDE de Arduino. En bas j'ai une fenetre qui me met des messages, dont les message d'erreur. En effet je ne vois pas de message d'erreur qaund je compile

    Tu ne peux pas. Un tel tableau est une variable locale à la fonction où elle est déclarée et sera détruite uniquement quand on quittera cette fonction. Tu ne pourras pas gagner de mémoire, comme tu ne pourras pas l'agrandir.
    Ok, j'ai bien compris. Mais si mon tableau contien le message bonjour et j'aimerais le vider, je veux dire que si je fait un Serial.print(monTableau) il ne m'affiche plus 'bonjours' mais rien comme si je faisait ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    char monTableau[20];
    Serial.print(monTableau); // Il n'affichera rien
    ceci ne fait pas cela?
    Au passage, essaye de respecter la règle "une question = une discussion".
    D'accord. Je voulais en fait éviter de faire deux post. Mais c'est noté

    Merci
    Il ne suffit pas de tout savoir. Vouloir et persévérer, c'est déjà presque tout!

  6. #6
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2013
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2013
    Messages : 21
    Points : 13
    Points
    13
    Par défaut
    Salut,
    Je crois plutôt que string est une chaine de caractère (char)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    char lettre = 'A'; \\un char
    char mot[4] = "mot"; \\une string
    pour "supprimer" ta string, c'est pas possible comme on te l'a indiqué plus haut. Par contre tu peux faire en sorte que rien de s'affiche en mettant le caractère de fin de chaine '\0' au premier caractère de ta string.
    attention ça ne change pas la longueur de ta chaine qui prendra toujours autant de place en mémoire.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    montableau[0]='\0';
    explications: on affecte le caractère de fin de chaine au premier caractère de ta chaine.

  7. #7
    Débutant  
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    3 096
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 096
    Points : 944
    Points
    944
    Par défaut
    D'acord merci.

    Donc c'est bien ca

    et pas

    Merci
    Il ne suffit pas de tout savoir. Vouloir et persévérer, c'est déjà presque tout!

  8. #8
    Invité
    Invité(e)
    Par défaut
    Bonsoir,

    Oui c'est bien montableau[0]='\0';.

    Par contre surtout pas montableau[20]='\0'; !
    Ton tableau possède 20 éléments, les indices vont donc de 0 à 19.
    Avec 20 tu dépasses.

  9. #9
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Les chaines

    Ben je doute de moi, mais j'ai envie de répondre oui.
    Oui je me trompe ou oui tu n'as pas bien compris ?

    Petit cours rapide sur les chaines de caractères en C

    char est un type d'entier de petite taille, généralement 8 bits. On s'en sert souvent pour y stocker des caractères codés selon ASCII. Ce n'est pas le seul type pour stocker des caractères. Un char est donc avant tout un nombre dont la valeur est interprétée comme un caractère.

    Une chaine de caractères est une suite de caractères et pour savoir quand elle se termine, le dernier élément de cette suite est un caractère spécial, '\0' dont la valeur numérique est 0. Ces caractères étant placés de manière consécutives en mémoire, il y a donc trois façons d'avoir un objet dit "chaine de caractères" :
    1. un tableau, qu'on déclare avec des crochets
    2. une zone allouée avec malloc() qui nous renvoie un pointeur sur le premier caractère
    3. une chaine littérale, non modifiable, placée en mémoire constante, accessible par un pointeur. Voir aussi la FAQ.

    A noter qu'une chaine littérale telle que "bonjour" qui, si j'ai bonne mémoire est appelée non pas string string litteral par la norme C, peut aussi servir à initialiser un tableau de char. Elle n'est alors pas placée en mémoire constante et sert juste de "sucre syntaxique" pour simplifier l'écriture du code. Voir les trois liens précédents.

    A noter aussi : le C ne possède pas de type nommé String --> ce type est donné par le C++.

    Mais si mon tableau contient le message bonjour et j'aimerais le vider, je veux dire que si je fait un Serial.print(monTableau) il ne m'affiche plus 'bonjours' mais rien
    Serial.print(), tout comme les fonctions C "normales" que sont printf() ou puts(), affiche la chaine passée en paramètre. Comment ? En affichant chacun des caractères jusqu'à rencontrer le caractère spécial de fin, '\0'. Si tu ne veux rien afficher, il faut donc mettre le fameux '\0' au tout début car il sera rencontré immédiatement et la fonction s'arrêtera tout de suite. Le contenu du tableau n'est pas modifié hormis ce caractère. Si tu fais montableau[1]='\0';, seul le premier caractère s'affichera (si le premier n'est pas lui-même \0';). Seul le premier compte.

    Attention, comme le rappelle très justement Winjerome, les indices de tableaux commencent à zéro.

    Il faut vraiment que tu prennes le temps de comprendre les chaines de caractères. C'est peut-être le point le plus complexe du langage, mais c'est très important de comprendre.


    Byte

    Un peu sur le "vrai" problème.

    Pour ceci je ne sais pas quoi te répondre. J'utilise l'IDE de Arduino. En bas j'ai une fenetre qui me met des messages, dont les message d'erreur. En effet je ne vois pas de message d'erreur qaund je compile
    Dire que tu codes sur l'IDE de l'Arduino est en fait suffisant A noter que le langage Arduino est un mélange de C et de C++. D'où les méthodes sur des objets tels que Serial.print() ou encore le type String probablement.

    Je présume aussi que le byte est défini par la bibliothèque Arduino.

    EDIT : gagné http://arduino.cc/en/Reference/Byte --> C'est donc unsigned char en toute logique. Il faut que je teste pour voir pourquoi c'est accepté.



    Bon courage.


    PS :
    D'accord. Je voulais en fait éviter de faire deux post. Mais c'est noté
    On évite d'écrire deux messages à la suite dans la même discussion ou de créer deux discussions dans deux forums différents pour le même problème. En revanche, deux questions = deux discussions

  10. #10
    Débutant  
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    3 096
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 096
    Points : 944
    Points
    944
    Par défaut
    Salut Bktero,

    Un grand merci pour ce petit cours. Oui je dois prendre du temps a bien comprendre les chaine de caractere.

    Je n'ose plus poser encore de question, mais le fait comme même

    char est un type d'entier de petite taille, généralement 8 bits. On s'en sert souvent pour y stocker des caractères codés selon ASCII. Ce n'est pas le seul type pour stocker des caractères. Un char est donc avant tout un nombre dont la valeur est interprétée comme un caractère.

    Une chaine de caractères est une suite de caractères et pour savoir quand elle se termine, le dernier élément de cette suite est un caractère spécial, '\0' dont la valeur numérique est 0.
    J'ai compreis que quand on affectera une valeur à
    char monChar[20];
    il se terminera pas un \0. Tout comme strcat, ajoute un \0 à la fin.
    Ce qui me rend confu, c'est que tu parle de chaine de caractere qui se termine par un \0 et pas le char.

    Oui je code sous Arduino et j'ai vu ceci

    Strind monString = "Mon string";
    C'est peut etre ca qui me porte a confusion, car j'interpretais ca comme un chaine de caractere et un char comme tableau

    Si tu fais montableau[1]='\0';
    Ok ca j'ai très bien compris

    Serial.print(), tout comme les fonctions C "normales" que sont printf() ou puts(), affiche la chaine passée en paramètre
    Par contre la je bloque encore avec puts()
    affiche la chaine passée en paramètre
    Que veux tu dire. Il affiche comme Serial.print(). C'est donc un equivalent de Serial.print()? C'est pourquoi de le mettre en commentaire, ca n'a empecher de faire fonctionner mon code? Mais par contre je n'ai rien vu sur mon terminal
    Je suis désolé, j'ai l'impression de poser des questions de gros débutant

    EDIT : gagné http://arduino.cc/en/Reference/Byte --> C'est donc unsigned char en toute logique. Il faut que je teste pour voir pourquoi c'est accepté.
    Oui alors j'aimerais bien comprendre, mais je vais me plonger a la lecture

    JE TE REMERCIE PLEINEMENT POUR TOUTES CES EXPLICATION

    Et desolé pour deux questions dans un post!!!
    Il ne suffit pas de tout savoir. Vouloir et persévérer, c'est déjà presque tout!

  11. #11
    Membre régulier Avatar de Mipwiq
    Homme Profil pro
    Inscrit en
    Avril 2013
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2013
    Messages : 42
    Points : 81
    Points
    81
    Par défaut
    Je vais appuyer l'explication Bktero :

    Pour manipuler des caractère en C tu as 3 types à connaitre et à comprendre.
    -char
    -char [x]
    -char *

    Le 1er est UN caractère ce n'est pas une chaine de caractère, ce type est comme l'explique Bktero généralement codé sur un octet.
    exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    char toto; // déclaration d'une variable de type char donc un caractère
    toto = 'c' // ce caractère prend la valeur 'c'
    putchar(toto) // affiche un caractère, ici toto
    Ensuite on peut déclarer des bloc de données ce sont les tableaux : char nomDeVariable[x]; où x est la taille du tableau (nombre de case) à ce moment on appelle ça une chaine de caractères.
    exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    char toto[7]; // on déclare un TABLEAU de char et non plus un char unique
    toto = {'c','o','u','c','o','u','\0'}; // on assigne une valeur à chaque case du tableau
    // On peut aussi le faire sur chaque case une par une
    toto[0] = 'c'; // ici on accède à la case 0 de toto qui est un char (exemple précédent)
    toto[1] = 'o'; // idem mais pour la case 1
    etc ...
    toto[7] = '\0';
    //pour l'afficher on peut faire un boucle qui parcours le tableau
    for (int i = 0;toto[i] != '\0';i = i + 1)
       putchar(toto[i]);
    Enfin la 3ème méthode est la plus importante on utilise aussi un tableau mais cette fois c'est un tableau dynamique on pourra changer sa taille à tous moments (presque). En vérité lors de la déclaration char *nomDeVariable c'est un pointeur et non un tableau, si tu utilises la fonction malloc pour assigner une valeur à ce pointeur alors il pointera sur la 1ère case d'un tableau dynamique que tu aura définis grâce à malloc.
    exemple:
    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
     
    char *toto; // On déclare un pointeur
     
    toto = malloc(7 * sizeof(char)); // Ligne à bien comprendre, malloc sert à faire pointer notre variable toto sur la 1ère case d'un tableau de char (sizeof(char)) constitué de 7 cases
    if (toto != NULL) // malloc peut bien sur échoué et renvoi dans ces cas là la valeur NULL, on vérifie donc bien la valeur de notre variable après le malloc
    {
      toto[0] = 'c'; // maintenant on peut manipuler notre variable comme dans l'exemple précédent
      toto[1] = 'o';
    etc ...
    // Ou on peut aussi faire :
      *toto = 'c' // Vu que notre variable est toujours un pointeur et qu'il est initialisé sur la 1ère case du tableau on peut aussi faire de cette manière pour remplir notre chaine de caractère
      toto += 1; // attention ceci déplace le pointeur si on veut le passer en paramètre il ne faut pas oublier de le remettre a sa valeur initiale
      *toto = 'o';
    etc...
    free(toto); // ne pas oublier dans ce cas de figure de libérer la mémoire allouée avec malloc grâce à free car ce genre de variables ne sont pas détruites à la sortie des bloc où elles sont créées  
    }
    Voilà j'espère que tu as bien compris la différence maintenant entre un char, un char [] et un char *

    Petit truc avant la fin, String comme le dit Bktero est un type de C++ et non de C, c'est un objet qui permet de manipuler des chaines de caractère qui n'existe donc pas en C.

  12. #12
    Débutant  
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    3 096
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 096
    Points : 944
    Points
    944
    Par défaut
    Milles mercis pour ces explications!!!!
    Me reste encore a comprendre pourquoi le int est accepter dans une fonction qui demande un byte
    Il ne suffit pas de tout savoir. Vouloir et persévérer, c'est déjà presque tout!

  13. #13
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Un petit couac au milieu de cette bonne explication :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char toto[7]; // on déclare un TABLEAU de char et non plus un char unique
    toto = {'c','o','u','c','o','u','\0'}; // on assigne une valeur à chaque case du tableau
    Cette écriture n'est pas correcte. En effet, on ne peut utiliser un initializer (une série de valeurs entre accolades)...... qu'au moment de l'initialisation ! Ce n'est pas possible lors d'une affectation comme c'est fait à la ligne 2.

    Je me permet au passage de signaler qu'un pointeur sur une zone "malloquée" et un tableau partage des outils syntaxiques (accès avec [] ou *) mais sont des entités très distinctes.

  14. #14
    Membre régulier Avatar de Mipwiq
    Homme Profil pro
    Inscrit en
    Avril 2013
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2013
    Messages : 42
    Points : 81
    Points
    81
    Par défaut
    pourquoi le int est accepter dans une fonction qui demande un byte
    Et bien si ce que dit Bktero est vrai sur la nature du type byte, c'est normal, le langage C effectue par défaut certaines conversions de type, comme par exemple des int en char.

    Et donc comme je le disais si le type byte correspond à un unsigned char, je pense que la conversion est faite automatiquement au moment ou tu envois un int.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 10
    Dernier message: 20/11/2011, 23h47
  2. Réponses: 0
    Dernier message: 17/11/2011, 16h35
  3. Réponses: 8
    Dernier message: 28/04/2008, 12h34
  4. Réponses: 19
    Dernier message: 04/06/2007, 17h12
  5. Réponses: 8
    Dernier message: 26/10/2006, 16h46

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