Différences entre les versions de « Le C »
(Page créée avec « == Avant-propos == Ce qui est proposé dans ce document est d’utiliser une structure (sa référence) comme argument de fonction et ainsi mettre en place un concept (que peut de gens se servent) proche de l’objet chère aux langage évolué comme le c++ Bien entendu pour éviter tout dépassement mémoire une partie de ce document traitera, le plus simplement possible, la gestion de la mémoire avec des références de structures plutôt qu’avec des point... ») |
m (réorganisation du code C avec SyntaxHighlightAce) |
||
Ligne 3 : | Ligne 3 : | ||
Ce qui est proposé dans ce document est d’utiliser une structure (sa référence) comme argument de fonction et ainsi mettre en place un concept (que peut de gens se servent) proche de l’objet chère aux langage évolué comme le c++ | Ce qui est proposé dans ce document est d’utiliser une structure (sa référence) comme argument de fonction et ainsi mettre en place un concept (que peut de gens se servent) proche de l’objet chère aux langage évolué comme le c++ | ||
Bien entendu pour éviter tout dépassement mémoire une partie de ce document traitera, le plus simplement possible, la gestion de la mémoire avec des références de structures plutôt qu’avec des pointeurs comme c’est souvent le cas. | <!--Bien entendu pour éviter tout dépassement mémoire une partie de ce document traitera, le plus simplement possible, la gestion de la mémoire avec des références de structures plutôt qu’avec des pointeurs comme c’est souvent le cas. | ||
…. | …. | ||
Ligne 10 : | Ligne 10 : | ||
Ainsi que d’éviter des fuites mémoire lors de l’utilisation d’arguments de fonction en employant une structure et sa référence ; c'est ce qui se rapproche plus de l’objet. | Ainsi que d’éviter des fuites mémoire lors de l’utilisation d’arguments de fonction en employant une structure et sa référence ; c'est ce qui se rapproche plus de l’objet. | ||
--> | |||
== Les données == | == Les données == | ||
Ligne 18 : | Ligne 19 : | ||
Pour créer une variable dont le contenu peut-être changeant on fait appel, avant tout, à « la déclaration de variable » : | Pour créer une variable dont le contenu peut-être changeant on fait appel, avant tout, à « la déclaration de variable » : | ||
<syntaxhighlight lang="cpp"> | |||
int valeur_numerique ; | int valeur_numerique ; | ||
char caractere ; | char caractere ; | ||
char tableau_dim [1024] ; | char tableau_dim [1024] ; | ||
char *pointeur ; | char *pointeur ; | ||
char **reference ; | char **reference ; | ||
Ligne 31 : | Ligne 30 : | ||
valeur_numerique = 65535 ; | valeur_numerique = 65535 ; | ||
caractere = 'c' ; | |||
tableau_dim = "une phrase qui en vaut une autre" ; | |||
pointeur = tableau_dim ; | |||
reference = &pointeur ; | |||
</syntaxhighlight> | |||
== Fonctions et appel de fonction == | == Fonctions et appel de fonction == | ||
Ligne 48 : | Ligne 45 : | ||
Syntaxe : | Syntaxe : | ||
<syntaxhighlight lang="cpp"> | |||
prototype Nom1(void) | prototype Nom1(void) | ||
{ | { | ||
Instructions, fonctions ou méthodes c'est du kiff... | |||
} | |||
</syntaxhighlight> | |||
Vrai fonction à placer : | Vrai fonction à placer : | ||
Ligne 61 : | Ligne 57 : | ||
''(à écrire dans un fichier nommé '''casdecole.cpp''')'' | ''(à écrire dans un fichier nommé '''casdecole.cpp''')'' | ||
< | <syntaxhighlight lang="cpp"> | ||
#include <iostream> /* pour le C dans un .c c koi pour printf ? */ | |||
int main'''(int argc, char *argv[], char **env)''' /* **env équivalent à *env[] */ | |||
{ | |||
printf("Nombre d’argument disponible lors de l'appel du programme '%s' est égal à '%d'\n", argv[0] , argc); | |||
printf("Nombre d’argument disponible lors de l'appel du programme '%s' est égal à '%d'\n", argv[0] , argc); | |||
/* La suite */ | |||
return(argc); | |||
} | } | ||
</syntaxhighlight> | |||
La fonction main() est la seule obligatoire pour qu'un programme soit exécuté par le système. Sinon le résultat produit fournirait une librairie , voire ci-dessous. | La fonction main() est la seule obligatoire pour qu'un programme soit exécuté par le système. Sinon le résultat produit fournirait une librairie , voire ci-dessous. | ||
Ligne 92 : | Ligne 87 : | ||
Fichier '''''casdecole.h''''' | Fichier '''''casdecole.h''''' | ||
<syntaxhighlight lang="cpp"> | |||
#ifndef CAS_D_ECOLE /* Si CAS_D_ECOLE n’est pas définie (ou utilisé) j’interprète les instructions suivante, SINON celle qui suivent le #endif qui me concerne… */ | |||
#define CAS_D_ECOLE | |||
/* Définition (ou alias/mini-macros ...) */ | /* Définition (ou alias/mini-macros ...) */ | ||
/* Inclusion de libraires ... */ | /* Inclusion de libraires ... */ | ||
/* Structures */ | /* Structures */ | ||
/* Prototypes ... */ | /* Prototypes ... */ | ||
#endif /* concerne le ifndef de CAS_D_ECOLE */ | |||
</syntaxhighlight> | |||
== Structure simple == | == Structure simple == | ||
Ligne 114 : | Ligne 107 : | ||
Syntaxe : | Syntaxe : | ||
struct NOM | <syntaxhighlight lang="cpp">struct NOM | ||
{ | { | ||
... Instructions ... | |||
... Instructions ... | |||
}; | }; | ||
</syntaxhighlight> | |||
Pour de vrai : | Pour de vrai : | ||
Ligne 126 : | Ligne 117 : | ||
''(à placer dans la partie /* Structures... */)'' | ''(à placer dans la partie /* Structures... */)'' | ||
<syntaxhighlight lang="cpp"> | |||
struct mes_options | struct mes_options | ||
{ | { | ||
int argc; | |||
int argc; | char **argv; | ||
char **env; | |||
char | |||
char | |||
}; | }; | ||
typedef mes options mon_projet_struct; | typedef mes options mon_projet_struct; | ||
</syntaxhighlight> | |||
== Fonctions et structures == | == Fonctions et structures == | ||
Ligne 147 : | Ligne 135 : | ||
Dans le '''''.h''''' : en dessous de /* Prototypes ... */ | Dans le '''''.h''''' : en dessous de /* Prototypes ... */ | ||
<syntaxhighlight lang="cpp"> | |||
void opt_main(mes_options *opt); | void opt_main(mes_options *opt); | ||
Ajouter ce qui est en gras dans le '''''casdecole.cpp''''' : | Ajouter ce qui est en gras dans le '''''casdecole.cpp''''' : | ||
#include <iostream> /* pour le C dans un .c c koi pour printf ? */ | |||
#include "casdecole.h" | |||
void opt_main(mes_option *opt) | void opt_main(mes_option *opt) | ||
{ | { | ||
int count = 1; | |||
printf( | printf(“les arguments disponibles sont : \n”); | ||
for( ; count < opt->argc ; count++) | |||
{ | |||
printf(" %4d: %s\n", count, opt.argv[count]); | |||
} | |||
} | } | ||
Ligne 176 : | Ligne 158 : | ||
{ | { | ||
mes_options opt; /* Création d'une instance de "mes_options" */ | |||
mes_options opt; /* Création d'une instance de "mes_options" */ | |||
/* représentée par "opt" */ | /* représentée par "opt" */ | ||
opt.argv = argv ; | opt.argv = argv ; | ||
opt.argc = argc; | |||
opt.argc = argc; | opt.env = env; | ||
opt.env = env; | |||
printf("Nombre d’argument disponible lors de l'appel du programme '%s' est égal à '%d'\n", argc, argv[0]); | printf("Nombre d’argument disponible lors de l'appel du programme '%s' est égal à '%d'\n", argc, argv[0]); | ||
/* La suite */ | /* La suite */ | ||
opt_main(&opt); | |||
return(argc); | |||
return(argc); | |||
} | } | ||
</syntaxhighlight> | |||
== Structures complexes == | == Structures complexes == | ||
Ligne 204 : | Ligne 183 : | ||
''(à ajouter dans notre .h)'' | ''(à ajouter dans notre .h)'' | ||
<syntaxhighlight lang="cpp"> | |||
typedef struct | typedef struct | ||
{ | { | ||
char *fonction; | |||
int droits ; | |||
/* déclaration de fonction (prototype) */ | |||
void (*function)(struct *mon_menu, char *, char *); | |||
void (*function)(struct *mon_menu, char *, char *) | |||
'''mon_menu''' *next ; | |||
'''mon_menu''' *prev ; | |||
} command_tbl; | } command_tbl; | ||
typedef '''mon_menu''' ma_structure_menu | typedef '''mon_menu''' ma_structure_menu | ||
</syntaxhighlight> | |||
Définir sa propre structure avant même qu'elle soit définie entièrement est quelque chose de plutôt abstrait pour un nom habitué. Cette possibilité est importante pour un programme devant gérer des listes de données (liste chaînée)… | Définir sa propre structure avant même qu'elle soit définie entièrement est quelque chose de plutôt abstrait pour un nom habitué. Cette possibilité est importante pour un programme devant gérer des listes de données (liste chaînée)… | ||
<syntaxhighlight lang="cpp"> | |||
/* Une autre façon de déclarer une structure dite ‘complexe’ */ | /* Une autre façon de déclarer une structure dite ‘complexe’ */ | ||
struct | struct | ||
{ | { | ||
char *nom; /* name of command */ | |||
char *nom; /* name of command */ | void (*function)(char *, char*, char*); /* pointer to function */ | ||
int userlvl; | |||
void (*function)(char *, char*, char*); /* pointer to function | |||
int userlvl; | |||
} on_msg_commands[] = | } on_msg_commands[] = | ||
Ligne 245 : | Ligne 215 : | ||
{ | { | ||
{ "HELP", show_help, 0, FALSE }, | |||
{ "DC", do_dc, 0, FALSE }, | |||
/* | |||
. | |||
: | |||
*/ | |||
/* | { NULL, null(void(*)()), 0, FALSE } | ||
. | |||
{ NULL, null(void(*)()), 0, FALSE } | |||
}; | }; | ||
Ligne 265 : | Ligne 228 : | ||
struct mon_menu | struct mon_menu | ||
{ | { | ||
"httpd", 100, do_httpd, | |||
"httpd", 100, do_httpd, | "echo", 0, do_echo, | ||
"echo", 0, | |||
} | } | ||
ma_structure_menu | ma_structure_menu | ||
{ | { | ||
} on_cmds[]; | } on_cmds[]; | ||
void do_menu(mon_menu opt) | void do_menu(mon_menu opt) | ||
{ | { | ||
/* fonction gérant les droits d'accès et exécution des argv */ | |||
/* fonction gérant les droits d'accès et exécution des argv */ | |||
} | } | ||
</syntaxhighlight> | |||
== static et extern == | == static et extern == | ||
Ligne 293 : | Ligne 248 : | ||
'''''fichier.c''''' | '''''fichier.c''''' | ||
<syntaxhighlight lang="cpp"> | |||
/* variable non accessible ailleur que dans ce fichier */ | /* variable non accessible ailleur que dans ce fichier */ | ||
Ligne 302 : | Ligne 258 : | ||
'''extern''' void la_fonction(void); | '''extern''' void la_fonction(void); | ||
</syntaxhighlight> | |||
Le compilateur fait ainsi l'économie de recherche dans le fichier de déclaration. Seul le linkeur fait cette recherche pour remplacer la référence par la définition. | Le compilateur fait ainsi l'économie de recherche dans le fichier de déclaration. Seul le linkeur fait cette recherche pour remplacer la référence par la définition. | ||
Ligne 310 : | Ligne 267 : | ||
'''const''' char *p1 = "mon discours"; | '''const''' char *p1 = "mon discours"; | ||
<syntaxhighlight lang="cpp"> | |||
char '''const''' *p2 = "mon discours 2"; | char '''const''' *p2 = "mon discours 2"; | ||
char *p3 '''const''' = "mon discours 3"; | char *p3 '''const''' = "mon discours 3"; | ||
</syntaxhighlight> | |||
Ces formes n'ont pas les même signification pour le compilateur… | Ces formes n'ont pas les même signification pour le compilateur… |
Version du 23 mai 2022 à 18:06
Avant-propos
Ce qui est proposé dans ce document est d’utiliser une structure (sa référence) comme argument de fonction et ainsi mettre en place un concept (que peut de gens se servent) proche de l’objet chère aux langage évolué comme le c++
Les données
Dans la grande majorité des cas, toutes informations transmises à un programme est stocké dans la mémoire de façon dynamique.
En C les valeurs qui peuvent être modifiées, dans la mémoire, sont représentées par des « variables » crées par des prototypes en tout genre…
Pour créer une variable dont le contenu peut-être changeant on fait appel, avant tout, à « la déclaration de variable » :
int valeur_numerique ;
char caractere ;
char tableau_dim [1024] ;
char *pointeur ;
char **reference ;
Remplissage des variables et première utilisation :
valeur_numerique = 65535 ;
caractere = 'c' ;
tableau_dim = "une phrase qui en vaut une autre" ;
pointeur = tableau_dim ;
reference = &pointeur ;
Fonctions et appel de fonction
Une fonction est un regroupement d’instructions pouvant être des conditions ou des changement d’état de la mémoire ( via les variables ou pointeurs).
Toutes ses instructions se placent dans un fichier ayant pour extension .cpp dans lequel peut y ajouter nos "définitions de fonctions".
Théorie : Définition de fonction simple :
Syntaxe :
prototype Nom1(void)
{
Instructions, fonctions ou méthodes c'est du kiff...
}
Vrai fonction à placer :
(à écrire dans un fichier nommé casdecole.cpp)
#include <iostream> /* pour le C dans un .c c koi pour printf ? */
int main'''(int argc, char *argv[], char **env)''' /* **env équivalent à *env[] */
{
printf("Nombre d’argument disponible lors de l'appel du programme '%s' est égal à '%d'\n", argv[0] , argc);
/* La suite */
return(argc);
}
La fonction main() est la seule obligatoire pour qu'un programme soit exécuté par le système. Sinon le résultat produit fournirait une librairie , voire ci-dessous.
Seul un code, avec main, pourrait s'en servir comme librairie (voyez là un dictionnaire d'instructions)...
Utilisation de librairies de fonctions
Une librairie est un magasin de fonctions organiser intelligemment pour faire gagner du temps au développement et permet au compilateur de perdre moins de temps lors d’une recompilation.
Pour être précis et rapide lorsque vous effectué des modifications dans un fichier de votre projet le compilateur va seulement recompiler le fichier modifié et non tout l’ensemble. Bien tendu il faut avoir organisé vos fonctions comme détaillé plus bas !
De façon générale il faut placer dans un fichier ayant pour extension '.h' (point H) tous les prototypes de fonction ainsi que les structures ; ceci permet au code d'être plus rapidement transformer dans les utilisations futures, mais pas seulement…
Une astuce fort utile dans un .h
Quelque soit l’utilisation que vous prévoyez de votre .h il faut prendre garde à ce qu’il ne soit pas relu par le compilateur afin d'éviter une erreur de compilation ou une mise en garde (warning) disant que certaines choses sont redéfinies ; ça fait mauvais genre et ça compile pas!
Pour éviter ce piège il faut placer les instructions à l'intérieur d'un #ifndef et #endif comme suit :
Fichier casdecole.h
#ifndef CAS_D_ECOLE /* Si CAS_D_ECOLE n’est pas définie (ou utilisé) j’interprète les instructions suivante, SINON celle qui suivent le #endif qui me concerne… */
#define CAS_D_ECOLE
/* Définition (ou alias/mini-macros ...) */
/* Inclusion de libraires ... */
/* Structures */
/* Prototypes ... */
#endif /* concerne le ifndef de CAS_D_ECOLE */
Structure simple
Une structure est un ensemble d'instructions servant principalement à diminuer le nombre d'argument à fournir à une fonction ou éviter les variables globales ; un fléau lorsqu'on veut modifier ou débugger son code…
Pensez à placer vos structures dans le .h, ici placer la vrai structure dans casdecole.h.
Syntaxe :
struct NOM
{
... Instructions ...
};
Pour de vrai :
(à placer dans la partie /* Structures... */)
struct mes_options
{
int argc;
char **argv;
char **env;
};
typedef mes options mon_projet_struct;
Fonctions et structures
Maintenant qu'il existe une structure il est possible de travailler sans utiliser de variable globale ou une multitude d'argument dans la fonction.
Voici le prototype à placer dans casdecole.h suivi de sa définition à écrire dans casdecole.cpp.
Dans le .h : en dessous de /* Prototypes ... */
void opt_main(mes_options *opt);
Ajouter ce qui est en gras dans le '''''casdecole.cpp''''' :
#include <iostream> /* pour le C dans un .c c koi pour printf ? */
#include "casdecole.h"
void opt_main(mes_option *opt)
{
int count = 1;
printf(“les arguments disponibles sont : \n”);
for( ; count < opt->argc ; count++)
{
printf(" %4d: %s\n", count, opt.argv[count]);
}
}
int main(int argc, char *argv[], char **env) /* **env équivalent à *env[] */
{
mes_options opt; /* Création d'une instance de "mes_options" */
/* représentée par "opt" */
opt.argv = argv ;
opt.argc = argc;
opt.env = env;
printf("Nombre d’argument disponible lors de l'appel du programme '%s' est égal à '%d'\n", argc, argv[0]);
/* La suite */
opt_main(&opt);
return(argc);
}
Structures complexes
Ce qui est appelé "structure complexe" est une structure simple avec soit sa propre structure en définition et/ou soit une déclaration d'un prototype de fonction. C’est-à-dire, non plus y stocker différents types de variable on y ajoute aussi des fonctions pour y être appelées par la structure elle-même.
Voici un exemple concret qui va se greffer au reste du projet :
(à ajouter dans notre .h)
typedef struct
{
char *fonction;
int droits ;
/* déclaration de fonction (prototype) */
void (*function)(struct *mon_menu, char *, char *);
'''mon_menu''' *next ;
'''mon_menu''' *prev ;
} command_tbl;
typedef '''mon_menu''' ma_structure_menu
Définir sa propre structure avant même qu'elle soit définie entièrement est quelque chose de plutôt abstrait pour un nom habitué. Cette possibilité est importante pour un programme devant gérer des listes de données (liste chaînée)…
/* Une autre façon de déclarer une structure dite ‘complexe’ */
struct
{
char *nom; /* name of command */
void (*function)(char *, char*, char*); /* pointer to function */
int userlvl;
} on_msg_commands[] =
/* Commande function userlvl forcedcc */
{
{ "HELP", show_help, 0, FALSE },
{ "DC", do_dc, 0, FALSE },
/*
.
:
*/
{ NULL, null(void(*)()), 0, FALSE }
};
''(à placer dans le .c)''
struct mon_menu
{
"httpd", 100, do_httpd,
"echo", 0, do_echo,
}
ma_structure_menu
{
} on_cmds[];
void do_menu(mon_menu opt)
{
/* fonction gérant les droits d'accès et exécution des argv */
}
static et extern
static rend une variable ou fonction accessible uniquement dans le fichier où c'est déclaré.
fichier.c
/* variable non accessible ailleur que dans ce fichier */
'''static''' int var_protect = 198;
'''extern''' déclare qu'une fonction est déclarée ailleurs que dans le fichier où elle est définie :
/* fonction déclarée ailleurs que dans ce fichier */
'''extern''' void la_fonction(void);
Le compilateur fait ainsi l'économie de recherche dans le fichier de déclaration. Seul le linkeur fait cette recherche pour remplacer la référence par la définition.
Le bon "const"
const règle l'accès à une données en lecture seule. Cette donné peut-être un emplacement mémoire, un pointeur ou une référence…
const char *p1 = "mon discours";
char '''const''' *p2 = "mon discours 2";
char *p3 '''const''' = "mon discours 3";
Ces formes n'ont pas les même signification pour le compilateur…