En suivant des MOOC sur le C, il est expliqué, que si l'on veut créer une fonction, il faut créer son prototype avant la boucle Main. Et si on veut séparer son code en fichiers, mettre les prototypes dans le .h te les fonctions dans le .c
Jusque la, pas de problème.
Mais pour Arduino, jusqu’à maintenant, j'ai toujours créer des fonctions (de type Void) sans prototype et en les plaçant après le Void Loop, et ça marche nickel...
Savez vous pourquoi, il n'y a pas besoin des prototypes avec Arduino ?
Je cherche a séparer mon code (Arduino) en plusieurs fichiers, si les prototypes ne sont pas utiles, pourquoi faire le .h
Es ce que l'explication ne viendrait pas du faite que les fonctions que j'ai créé ne retourne pas de valeurs ?
Ce que dit pepe est vrai mais nécessite une bonne connaissance du C/C++.
Ce qu’il faut retenir c’est le que compilateur doit avoir été averti de l’existance d’une fonction avant tout appel a cette fonction.
Perso je ne suis pas un vrai programmeur et je pré-déclare systématiquement.
Si je décompose mon programme en plusieurs fichiers :
Pour les fichiers supplémentaires j’utilise les extensions c ou cpp.
Pour chaque fichier j’écris le fichier d’entête *.h qui contient les déclarations des fonctions ou des classes.
J’inclue ces fichiers *.h dans le fichier *.ino à l’aide de # include …
La syntaxe pour déclarer ces fichiers diffère selon l’emplacement des fichiers d’entête.
L’IDE fabrique le fichier “makefile” selon ses propres règles qui déterminent 3 emplacements officiels :
1 → dans la partie “core” de l’IDE pour les bibliothèques qui dépendent directement d’Arduino
2 → dans un autre répertoire de l’IDE pour les bibliothèques qui dépendent de tierces parties validées par arduino
3 → dans le répertoire “libraries” de ton répertoire personnel arduino pour toutes les autres bibliothèques.
Dans ce cas la syntaxe est #include <nom-fichier.h>
Si tu décompose ton programme en plusieurs fichiers ces fichiers seront dans le répertoire qui contient le fichier *.ino.
Il faudra alors dire au compilateur d’aller les chercher dans ce répertoire courant.
Cela se fait en remplaçant les < > par des " " (c’est une règle du C/C++)
include “nom-fichier.h”
Dernier point : si tu utilises des variables globales :
Les variables globales sont définies dans le fichier *.ino.
Une variable ne doit être déclarée qu’une seule fois mais chaque fichier est compilé séparément.
Pour les fichiers C/Cpp il faut prévenir le compilateur que ces variables ont déjà été déclarées ailleurs.
Cela se fait en ajoutant le mot clé “extern” :
Fichier *.ino :
int machin ; // déclaration
Fichier C/Cpp :
extern int machin ; // annonce au compilateur que la variable machin est de type int et qu’elle a déjà été déclarée ailleurs.
68tjs:
Cela se fait en ajoutant le mot clé "extern" :
Fichier *.ino :
int machin ; // déclaration
Fichier C/Cpp :
extern int machin ; // annonce au compilateur que la variable machin est de type int et qu'elle a déjà été déclarée ailleurs.
Bonjour,
Je constate que de plus en plus, y compris dans les tutos et cours sur internet on emploie déclaration pour définition
De ce que j'ai retenu de mon apprentissage du C qui commence à remonter à pas mal d'années c'est que:
int machin ; // c'est une définition (qui vaut aussi déclaration)
extern int machin ; // c'est une déclaration
Suis je obsolète? Est ce que la terminologie a changé (sans qu'on me prévienne )?
Suis je obsolète? Est ce que la terminologie a changé (sans qu'on me prévienne )
Non tu te mets simplement à ma place quand je vois utiliser les termes pull-up et pull-down a tort et à travers en faisant simplement référence à la position géographique sur le schéma et en oubliant, méconnaissant, méprisant totalement le coté fonctionnel.
Donc promis j'essayerais de me rappeler de ta mise au point.
Etant un éternel optimiste j'ose espérer que, peut être, d'autres se rappelleront mes rappels incessant.
On utilise des variables globales uniquement si c'est nécessaire. Autrement on utilise des variables locales.
C'est vrai que dans beaucoup d'exemples de code arduino, toutes les variables sont définies au début du fichier .ino.
A mon avis c'est à proscrire, ça va complètement à l'encontre de la modularité. De plus quand on analyse une fonction, il faut retrouver les variables pour savoir de quoi il s'agit et en plus on ne sait jamais si c'est une vraie variable globale modifiée par ailleurs ou si c'est simplement une variable locale qui a été déclarée en globale.
Merci pour ton retour. Effectivement beaucoup de tuto, mooc, livre ect... utilise les variables globale pour Arduino.
Quand tu dis
ça va complètement à l'encontre de la modularité.
, tu veux dire quoi ?
J'essaye de comprendre le pour et le contre de ces deux philosophies et j'ai l'impression que les variables globales on l'air plus facile a coder ( moins de gymnastique de fonction a fonction...)
J'ai une déclaration de variable avec enum {value1, value2,...} dans le .ino
Evidement ces variables se retrouvent dans une fonction que je souhaite déplacer dans un autre fichier.
Donc dans le .c je déclare extern enum {value1, value2,...}
J'ai ce message d'erreur
error: a storage class can only be specified for objects and functions
enum {value1, value2} ce n'est pas la définition d'une variable, mais la définition d'un type énuméré.
la définition d'une variable serait enum {value1, value2} val;
elle pourrait être partagée par extern enum {value1, value2} val;, mais la définition de l'enum entrerait en conflit avec la définition de l'enum dans la définition de la variable dans le fichier ou elle est définie.
C'est pour ça qu'on utilise des enum nommés
dans le .h
enum EVAL {value1, value2}; // définition de l'enum EVAL
extern EVAL val; // déclaration de la variable val
extern EVAL val; // déclaration de la variable val
ca vaut int val
Je suis en train de réaliser une machine pour résoudre les Rubik's cube.
Pour tester mon solver, j'utilise enum pour attribuer les couleurs au face du cube.
Et je souhaiterai déplacer les void configuration 1 & 2 dans un autre fichier.
Tu utilises les enum comme de simples constantes numériques.
Ceci est autorisé en C++ car ce langage n'est pas très strict avec les correspondances de types
Moi je ne propose rien, j'explique le fonctionnement des enum
COULEUR cubeFace[6][8]; -> crée un tableau de variables de type COULEUR
byte cubeFace[6][8]; -> crée un tableau de type byte
Comme je l'ai expliqué, en C++ il y a un transtypage automatique entre un type enum (comme COULEUR) et un numérique
L'inverse n'est pas forcément vrai
Si tu déclares COULEUR cubeFace[6][8]; et que tu fais cubeface[0][0]=1, le compilateur devrait donner une erreur (ce que ne fait pas le compilateur de l'IDE arduino).
D'autres langages sont beaucoup moins permissifs que le C++.
pepe:
Au final, on peut être amené à écrire un même programme très différemment selon que l'on cherche à avoir un code très rapide, un code qui consomme peu de mémoire vive, ou un code qui consomme peu de mémoire programme.