<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[[Cours #5] ArgC, ArgV et allocations Dynamiques]]></title><description><![CDATA[<p dir="auto">&lt;p&gt;Bonjour à tous,&lt;br/&gt;<br />
Bienvenue dans ce 4ième cours sur la programmation en C.&lt;br/&gt;<br />
Aujourd'hui, nous allons voir un point intéréssent de notre programme, et un point clé en <img src="https://melinyel.net/assets/plugins/nodebb-plugin-emoji/emoji/android/1f604.png?v=d0a000c383a" class="not-responsive emoji emoji-android emoji--smile" style="height:23px;width:auto;vertical-align:middle" title="C:" alt="😄" /> les&lt;br/&gt;<br />
Arguments de lancement, et les allocations dynamiques.&lt;/p&gt;<br />
&lt;p&gt;&lt;strong&gt;I- Qu'est-ce qu'un argument de lancement?&lt;/strong&gt;&lt;br/&gt;<br />
Un argument de lancement est une string ajoutée au lancement du programme permettant de faire passer ladite string au programme (string = chaine de caractères).&lt;br/&gt;<br />
Ainsi, si je lance le programme avec cette ligne de commande:&lt;/p&gt;<br />
&lt;blockquote class="ipsQuote" data-ipsquote=""&gt;&lt;div&gt;mon_programme mon_argument<br />
&lt;p&gt; &lt;/p&gt;<br />
&lt;/div&gt;&lt;/blockquote&gt;<br />
&lt;p&gt;mon programme recevra comme argument 1 : "mon_argument".&lt;br/&gt;<br />
(En faite, d'une façon générale, les arguments sont gérés par les shells qui lancent le programme. C'est une convention de programmation).&lt;br/&gt;<br />
Quelques exemples d'utilisations d'arguments:&lt;br/&gt;<br />
Les commandes unix utilisent très souvent les arguments:&lt;/p&gt;<br />
&lt;blockquote class="ipsQuote" data-ipsquote=""&gt;&lt;div&gt;ls --help&lt;br/&gt;<br />
cd --&lt;br/&gt;<br />
cd /home&lt;br/&gt;<br />
cd ~&lt;br/&gt;<br />
mkdir test&lt;br/&gt;<br />
...<br />
&lt;p&gt; &lt;/p&gt;<br />
&lt;/div&gt;&lt;/blockquote&gt;<br />
&lt;p&gt;et peuvent donc permettre de faire passer une valeur, ou même un chemin à son programme (bah oui, c'est des Strings (tableaux de caractères). Bon, passons à la pratique:&lt;/p&gt;<br />
&lt;p&gt;&lt;strong&gt;II- Récupérer des arguments de lancement&lt;/strong&gt;&lt;br/&gt;<br />
Nous avions vu la structure basique d'un main en C:&lt;/p&gt;<br />
&lt;pre class="ipsCode prettyprint"&gt;<br />
int main(void)<br />
{<br />
}&lt;/pre&gt;<br />
&lt;p&gt;<br />
Eh bien, je ne vous ai pas dit la vérité sur cette fonction!&lt;br/&gt;<br />
En effet, main peut prendre un void pour argument (et donc ne prendre aucun arguments), ou bien prendre un int, et un char **.&lt;br/&gt;<br />
Le véritable prototypage de la fonction main est donc:&lt;/p&gt;<br />
&lt;pre class="ipsCode prettyprint"&gt;<br />
int main(int argc, char *<em>argv)<br />
{<br />
}&lt;/pre&gt;<br />
&lt;p&gt;<br />
En voyant ça, vous allez me dire "dis donc, j'ai mal à la tête, y'a un ** dans ton code!" Eh bien ne&lt;br/&gt;<br />
vous inquiétez pas, il s'agit d'un tableau de chaines de caractères.Prenons pour exemple ce programme lancé comme ceci:&lt;/p&gt;<br />
&lt;pre class="ipsCode prettyprint"&gt;<br />
coucou arg1 arg2 arg3 je suis fou<br />
&lt;/pre&gt;<br />
&lt;p&gt;Eh bien, nous pouvons récupérer les arguments de ce programme de la façon suivante:&lt;/p&gt;<br />
&lt;pre class="ipsCode prettyprint"&gt;<br />
/</em><br />
** Je re-crée les fonctions d'affichage. Voir cours #1 et #2<br />
*/<br />
void my_putchar(char c)<br />
{<br />
write(1, &amp;c, 1);<br />
}</p>
<p dir="auto">void my_putstr(char *str)<br />
{<br />
while(<em>str)<br />
my_putchar(</em>(str++));<br />
}</p>
<p dir="auto">int main(int argc, char **argv)<br />
{<br />
my_putstr(argv[0]); // Affichera<br />
my_putstr(argv[1]); // Affichera<br />
my_putstr(argv[2]); // Affichera<br />
my_putstr(argv[3]); // Affichera<br />
my_putstr(argv[4]); // Affichera<br />
my_putstr(argv[5]); // Affichera<br />
my_putstr(argv[6]); // Affichera<br />
return (0);<br />
}<br />
&lt;/pre&gt;<br />
&lt;blockquote class="ipsQuote" data-ipsquote=""&gt;&lt;div&gt;"cocuou"&lt;br/&gt;<br />
"arg1"&lt;br/&gt;<br />
"arg2"&lt;br/&gt;<br />
"arg3"&lt;br/&gt;<br />
"je"&lt;br/&gt;<br />
"suis"&lt;br/&gt;<br />
"foud"<br />
&lt;p&gt; &lt;/p&gt;<br />
&lt;/div&gt;&lt;/blockquote&gt;<br />
&lt;p&gt;Nous butons à présent sur un problème, ré-utilisons le programme précédent, mais supprimons tous,&lt;br/&gt;<br />
ou un des arguments:&lt;/p&gt;<br />
&lt;blockquote class="ipsQuote" data-ipsquote=""&gt;&lt;div&gt;Segmentation Fault<br />
&lt;p&gt; &lt;/p&gt;<br />
&lt;/div&gt;&lt;/blockquote&gt;<br />
&lt;p&gt;<br />
Eh oui, comme vous le voyez, nous essayons d'accéder à la valeur d'un tableau qui n'existe pas, ce qui provoque une erreur d'accès en mémoire.&lt;br/&gt;<br />
Pour remédier à cela, les développeurs nous ont rajoutés "argc".&lt;br/&gt;<br />
Pour mieux vous faire comprendre, je vais vous définir exactement ce que signifie argc et argv:&lt;br/&gt;<br />
ArgC est un couplage entre les mots: Argument et Count, il s'agit donc du nombre d'arguments qui ont été passés en paramètres.&lt;br/&gt;<br />
ArgV est un couplage entre les mots: Argument et Value, il s'agit donc des valeurs de ces dits arguments.&lt;/p&gt;<br />
&lt;p&gt;<br />
Maintenant que vous avez le nombre d'arguments, vous pouvez vérifier que le nombre d'arguments est correcte avant de l'afficher:&lt;/p&gt;<br />
&lt;pre class="ipsCode prettyprint"&gt;<br />
int main(int argc, char **argv)<br />
{<br />
if (argc &gt; 1)<br />
my_putstr(argv[1]);<br />
return (0);<br />
}&lt;/pre&gt;<br />
&lt;p&gt;argv[0] sera toujours présent, puisqu'il s'agit du tout premier argument, qui est vital pour lancer le programme (il s'agit plus exactement de la commande utilisée pour lancer le programme).&lt;br/&gt;<br />
Passons à présent à la partie complexe de ce cours: les allocations dynamiques.&lt;/p&gt;<br />
&lt;p&gt;&lt;strong&gt;III- Les allocations dynamiques&lt;/strong&gt;&lt;br/&gt;<br />
L'allocation dynamique, c'est l'art de savoir utiliser sa RAM et les répercussions de l'alloc sur celle-ci.&lt;br/&gt;<br />
Nous avions vu précédemment que pour pouvoir avoir une chaine de caractère avec une certaine taille, nous devions définir un tableau de caractères, avec une taille FIXE.&lt;br/&gt;<br />
Comme ceci:&lt;/p&gt;<br />
&lt;pre class="ipsCode prettyprint"&gt;<br />
char mon_tableau[talle_de_mon_tableau];<br />
&lt;/pre&gt;<br />
&lt;p&gt;Là est le problème, imaginons que nous devions modifier notre chaine, en lui imposant une taille plus grande: SegFault.&lt;br/&gt;<br />
Eh bien, la solution, c'est d'utiliser l'allocation dynamique: Au lieu de stocker notre chaine dans la stack, stockons la dans la RAM! (ce qui nous permet d'avoir plus d'espace, d'ailleurs! (généralement, la stack est limitée à quelques Ko, alors que la RAM non))&lt;br/&gt;<br />
Vous comprenez donc qu'il est dangereux d'utiliser malloc de façon idiote: dans une boucle infinie par exemple... Puisque vous allez remplir votre RAM!&lt;/p&gt;<br />
&lt;p&gt;<br />
Prenons un exemple simple:&lt;br/&gt;<br />
J'ai un programme qui connaît la taille d'une chaine de caractère, et je dois la stocker dans une variable:&lt;/p&gt;<br />
&lt;pre class="ipsCode prettyprint"&gt;<br />
int main(void)<br />
{<br />
int lenght = 300000; // Oui, notre chaine est très longue<br />
}&lt;/pre&gt;<br />
&lt;p&gt;<br />
Si je tentais de déclarer un tableau statique de char de taille 300 000, il y aura énormément de chances pour que mon programme segfault dès le lancement.&lt;br/&gt;<br />
C'est problématique, en effet.&lt;br/&gt;<br />
Tentons donc d’allouer un emplacement dans la ram pour cette chaine:&lt;/p&gt;<br />
&lt;pre class="ipsCode prettyprint"&gt;<br />
int main(void)<br />
{<br />
char *ptr;</p>
<p dir="auto">ptr = malloc(300000 * sizeof(char));<br />
}&lt;/pre&gt;<br />
&lt;p&gt;<br />
Tiens, ça marche!&lt;br/&gt;<br />
Lisons un peu mieux le man de malloc: en cas d'erreur, malloc retourne NULL.&lt;br/&gt;<br />
Nous allons donc vérifier si il y a eu une erreur (pour éviter le segfault):&lt;/p&gt;<br />
&lt;pre class="ipsCode prettyprint"&gt;<br />
int main(void)<br />
{<br />
char <em>ptr;<br />
ptr = malloc(300000 * sizeof(char));<br />
if (ptr == NULL)<br />
{<br />
my_putstr("Erreur malloc\n");<br />
return ;<br />
}<br />
}&lt;/pre&gt;<br />
&lt;p&gt;<br />
Bon, nous avons donc alloué un emplacement de type char</em> (donc tableau de caractères) dans notre ram, avec une taille de 300 000 cases! Cool!&lt;br/&gt;<br />
Nous pouvons donc remplire "ptr" exactement comme un tableau (case par case, voir cours sur les chaines de caractères).&lt;br/&gt;<br />
ATTENTION: ptr est un POINTEUR. Si vous modifiez son adresse, vous perdez l'ancienne adresse allouée! Donc ceci:&lt;/p&gt;<br />
&lt;pre class="ipsCode prettyprint"&gt;<br />
int main(void)<br />
{<br />
char *ptr;</p>
<p dir="auto">ptr = malloc(300000 * sizeof(char));<br />
if (ptr == NULL)<br />
{<br />
my_putstr("Erreur malloc\n");<br />
return ;<br />
}<br />
ptr = "coucou";<br />
}<br />
&lt;/pre&gt;<br />
&lt;p&gt;est interdit et stupide (ne rigolez pas, les profs de programmation font souvent l'erreur!).&lt;br/&gt;<br />
Bon, c'est bien, nous avons alloué de la mémoire, mais bon, c 'est pas cool pour la RAM, on ne la vide jamais, il va falloir la vider!&lt;br/&gt;<br />
Pour la vider, la fonction "free" est là pour nous aider!&lt;br/&gt;<br />
Voilà mon programme une fois la fonction "free" utilisée:&lt;/p&gt;<br />
&lt;pre class="ipsCode prettyprint"&gt;<br />
int main(void)<br />
{<br />
char *ptr;</p>
<p dir="auto">ptr = malloc(300000 * sizeof(char));<br />
if (ptr == NULL)<br />
{<br />
my_putstr("Erreur malloc\n");<br />
return ;<br />
}<br />
free(ptr);<br />
}<br />
&lt;/pre&gt;<br />
&lt;p&gt;Tout marche! Cool!&lt;br/&gt;<br />
ATTENTION: pour bien vous montrer que modifier un pointeur est une mauvaise idée, tentez de faire ceci:&lt;/p&gt;<br />
&lt;pre class="ipsCode prettyprint"&gt;<br />
int main(void)<br />
{<br />
char *ptr;</p>
<p dir="auto">ptr = malloc(300000 * sizeof(char));<br />
if (ptr == NULL)<br />
{<br />
my_putstr("Erreur malloc\n");<br />
return ;<br />
}<br />
ptr = "coucou";<br />
free(ptr);<br />
}&lt;/pre&gt;<br />
&lt;p&gt;<br />
Hop, vous tomberez sur une erreur qui se nomme "glibC" et qui corresponds à une erreur de pointage, la fonction "free" vous hurle dessus comme quoi votre pointeur ne pointe pas sur une zone&lt;br/&gt;<br />
allouée.&lt;br/&gt;<br />
Pour vous montrer que mon code fonctionne, je vais afficher ma chaine de caractère, qui fera&lt;br/&gt;<br />
l'alphabet avec 300 000 lettres!&lt;/p&gt;<br />
&lt;pre class="ipsCode prettyprint"&gt;<br />
int main(void)<br />
{<br />
char *ptr;<br />
int i;</p>
<p dir="auto">i = 0;<br />
j = 0;<br />
ptr = malloc(300000 * sizeof(char));<br />
if (ptr == NULL)<br />
{<br />
my_putstr("Erreur malloc\n");<br />
return ;<br />
}<br />
while(i &lt; 300000)<br />
{<br />
ptr[i] = j + 'a';<br />
i = i + 1;<br />
j = j + 1;<br />
if (j + 'a' &gt;= 'z')<br />
j = 0;<br />
}<br />
ptr[i] = '\0'; // NE PAS OUBLIER LA FIN DE LA CHAINE (voir cours sur les chaines de caractères)<br />
my_putstr(ptr);<br />
free(ptr);<br />
}&lt;/pre&gt;<br />
&lt;p&gt;<br />
Et voilà, vous savez à présent utiliser les allocations dynamiques!&lt;br/&gt;<br />
A bientôt pour le prochain cours!&lt;br/&gt;<br />
Cours écrit par AlexMog. Contact: alexmog [at] live [point] fr&lt;/p&gt;</p>
]]></description><link>https://melinyel.net/topic/744/cours-5-argc-argv-et-allocations-dynamiques</link><generator>RSS for Node</generator><lastBuildDate>Wed, 02 Sep 2026 04:35:20 GMT</lastBuildDate><atom:link href="https://melinyel.net/topic/744.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 22 May 2014 14:08:36 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to [Cours #5] ArgC, ArgV et allocations Dynamiques on Sun, 25 May 2014 13:42:52 GMT]]></title><description><![CDATA[<p dir="auto">&lt;blockquote class="ipsQuote" data-cite="davydavek" data-ipsquote="" data-ipsquote-contentclass="forums_Topic" data-ipsquote-contentcommentid="8006" data-ipsquote-contentid="744" data-ipsquote-contenttype="forums" data-ipsquote-timestamp="1400960511" data-ipsquote-username="davydavek"&gt;&lt;div&gt;<br />
&lt;div&gt;<br />
&lt;p&gt;J'ajouterais aussi que &lt;a href="<a href="http://valgrind.org/docs/manual/mc-manual.html" rel="nofollow ugc">http://valgrind.org/docs/manual/mc-manual.html</a>" rel="external nofollow"&gt;Valgrind-Memcheck&lt;/a&gt; est très utile pour détecter les erreurs liées a l'allocation dynamique.&lt;/p&gt;<br />
&lt;p&gt; &lt;/p&gt;<br />
&lt;p&gt;Pour l'utiliser : &lt;/p&gt;<br />
&lt;pre class="ipsCode prettyprint"&gt;<br />
valgrind ./votreprogramme<br />
&lt;/pre&gt;<br />
&lt;p&gt;Et avec un makefile c'est encore plus simple  <img src="https://melinyel.net/assets/plugins/nodebb-plugin-emoji/emoji/android/1f609.png?v=d0a000c383a" class="not-responsive emoji emoji-android emoji--wink" style="height:23px;width:auto;vertical-align:middle" title=";)" alt="😉" /> &lt;/p&gt;<br />
&lt;/div&gt;<br />
&lt;/div&gt;&lt;/blockquote&gt;<br />
&lt;p&gt;L'utiliser pour les memory leaks et aussi très intéréssente <img src="https://melinyel.net/assets/plugins/nodebb-plugin-emoji/emoji/android/1f609.png?v=d0a000c383a" class="not-responsive emoji emoji-android emoji--wink" style="height:23px;width:auto;vertical-align:middle" title=";)" alt="😉" /> .&lt;/p&gt;<br />
&lt;p&gt;J'ai déjà cité Valgrind dans le cours #0 justement <img src="https://melinyel.net/assets/plugins/nodebb-plugin-emoji/emoji/android/1f609.png?v=d0a000c383a" class="not-responsive emoji emoji-android emoji--wink" style="height:23px;width:auto;vertical-align:middle" title=";)" alt="😉" /> .&lt;/p&gt;<br />
&lt;p&gt; &lt;/p&gt;<br />
&lt;p&gt;GDB est aussi parfait pour ce genre de travail.&lt;/p&gt;</p>
]]></description><link>https://melinyel.net/post/8034</link><guid isPermaLink="true">https://melinyel.net/post/8034</guid><dc:creator><![CDATA[AlexMog]]></dc:creator><pubDate>Sun, 25 May 2014 13:42:52 GMT</pubDate></item><item><title><![CDATA[Reply to [Cours #5] ArgC, ArgV et allocations Dynamiques on Sat, 24 May 2014 19:41:51 GMT]]></title><description><![CDATA[<p dir="auto">&lt;p&gt;J'ajouterais aussi que &lt;a href="<a href="http://valgrind.org/docs/manual/mc-manual.html" rel="nofollow ugc">http://valgrind.org/docs/manual/mc-manual.html</a>" rel="external nofollow"&gt;Valgrind-Memcheck&lt;/a&gt; est très utile pour détecter les erreurs liées a l'allocation dynamique.&lt;/p&gt;<br />
&lt;p&gt; &lt;/p&gt;<br />
&lt;p&gt;Pour l'utiliser : &lt;/p&gt;<br />
&lt;pre class="ipsCode prettyprint"&gt;<br />
valgrind ./votreprogramme<br />
&lt;/pre&gt;<br />
&lt;p&gt;Et avec un makefile c'est encore plus simple  <img src="https://melinyel.net/assets/plugins/nodebb-plugin-emoji/emoji/android/1f609.png?v=d0a000c383a" class="not-responsive emoji emoji-android emoji--wink" style="height:23px;width:auto;vertical-align:middle" title=";)" alt="😉" /> &lt;/p&gt;</p>
]]></description><link>https://melinyel.net/post/8006</link><guid isPermaLink="true">https://melinyel.net/post/8006</guid><dc:creator><![CDATA[davydavek]]></dc:creator><pubDate>Sat, 24 May 2014 19:41:51 GMT</pubDate></item><item><title><![CDATA[Reply to [Cours #5] ArgC, ArgV et allocations Dynamiques on Fri, 23 May 2014 08:25:28 GMT]]></title><description><![CDATA[<p dir="auto">&lt;p&gt;J'adore tes tutoriels : longs (très longs et tant mieux), complets et fournis. <img src="https://melinyel.net/assets/plugins/nodebb-plugin-emoji/emoji/android/1f642.png?v=d0a000c383a" class="not-responsive emoji emoji-android emoji--slightly_smiling_face" style="height:23px;width:auto;vertical-align:middle" title=":)" alt="🙂" /> &lt;/p&gt;<br />
&lt;p&gt;Tu mérites tout à fait ton grade.&lt;br/&gt;&lt;br/&gt;<br />
+1 rep.&lt;/p&gt;</p>
]]></description><link>https://melinyel.net/post/7925</link><guid isPermaLink="true">https://melinyel.net/post/7925</guid><dc:creator><![CDATA[Azad]]></dc:creator><pubDate>Fri, 23 May 2014 08:25:28 GMT</pubDate></item></channel></rss>