Contenu | Rechercher | Menus

Annonce

DVD, clés USB et t-shirts Ubuntu-fr disponibles sur la boutique En Vente Libre

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 26/09/2020, à 14:28

zephyre123

Deux programmes différents qui font exactement la même chose ?[RESOLU]

Bonjour,

Voici le premier programme qui permet d'initialiser une matrice à 0 ci dessous :

#include <stdio.h>
#include <stdlib.h>

int matrice[2][3] =
{
	{1, 2, 3},
	{4, 5, 6},
};

void initialisation(int (*pMatrice)[2][3])
{
	for(int i = 0; i < 2; i++)
		for(int j = 0; j < 3; j++)
			(*pMatrice)[i][j] = 0;

	for(int i = 0; i < 2; i++)
		for(int j = 0; j < 3; j++)
			printf("pMatrice[%d][%d] = %d\n",i, j, (*pMatrice)[i][j]);
}

int main(void)
{
	initialisation(&matrice);

	return EXIT_SUCCESS;
}

Voici le deuxième programme qui permet d'initialiser une matrice à 0 :

#include <stdio.h>
#include <stdlib.h>

int matrice[2][3] =
{
	{1, 2, 3},
	{4, 5, 6},
};

void initialisation(int (*pMatrice)[2][3])
{
	for(int i = 0; i < 2; i++)
		for(int j = 0; j < 3; j++)
			*pMatrice[i][j] = 0;

	for(int i = 0; i < 2; i++)
		for(int j = 0; j < 3; j++)
			printf("pMatrice[%d][%d] = %d\n",i, j, *pMatrice[i][j]);
}

int main(void)
{
	initialisation(&matrice);

	return EXIT_SUCCESS;
}


Je ne comprends pas pourquoi ces deux programmes font exactement la même chose ?
Moi je pensais que seul le premier c'est à dire (*pMatrice) fonctionne c'est à dire un pointeur sur matrice.
Dans le deuxième programme on a *pMatrice qui est une matrice de pointeur d'entier et la ça colle plus du tout.

Es ce que vous avez une explication ?

Dernière modification par zephyre123 (Le 04/10/2020, à 14:44)

Hors ligne

#2 Le 26/09/2020, à 15:22

kamaris

Re : Deux programmes différents qui font exactement la même chose ?[RESOLU]

Ils ne font pas la même chose, simplement comme il y a cohérence des écritures entre l'affectation et l'affichage dans chaque programme, tu affectes 0 puis tu affiches 0 dans les deux cas.
Mais le premier programme fait ce que tu penses, alors que le second en a seulement l'air, tandis qu'en mémoire, il fait autre chose.

Fais l'expérience suivante pour t'en convaincre :

#include <stdio.h>
#include <stdlib.h>

typedef int matrice[2][3];

void initialise_matrice (matrice *pm)
{
  int i, j;

  for (i = 0; i < 2; i++)
    for (j = 0; j < 3; j++)
      (*pm)[i][j] = 0;
}

void affiche_matrice (matrice m)
{
  int i, j;

  for (i = 0; i < 2; i++)
    for (j = 0; j < 3; j++)
      printf ("Matrice[%d][%d] = %d\n", i, j, m[i][j]);
}

int main (void)
{
  matrice m;

  initialise_matrice (&m);
  affiche_matrice (m);

  return EXIT_SUCCESS;
}

Fais tourner ce programme, qui fonctionne tel quel, puis enlève les parenthèses autour de *pm dans initialise_matrice().

--
PS : j'aurais dû tout écrire moi-même de a à z, parce que là, 10 minutes après, j'en suis encore à corriger les espacements ! big_smile

Dernière modification par kamaris (Le 26/09/2020, à 15:35)

Hors ligne

#3 Le 26/09/2020, à 21:28

zephyre123

Re : Deux programmes différents qui font exactement la même chose ?[RESOLU]

Bonsoir Kamaris,

Effectivement les deux programmes ne donne pas le même résultat :
Le deuxième programme me donne des valeurs aléatoires je l'ai lancé plusieurs fois et on obtient pas les mêmes valeurs sans compter que j'ai deux erreurs :
- *** stack smashing detected ***: <unknown> terminated
- Abandon (core dumped)

C'est ceux à quoi je m'attendais initialement la c'est plus cohérent au moins.
Cependant je ne comprends toujours pas pourquoi dans les deux programmes que je vous ai présentés on a justement pas ce type d'erreur et que la ça passe crème.
Il y a quelque chose que je ne comprends pas en mémoire je pense car pour moi cette écriture (*pMatrice[]) devrai entraîner une erreur car c'est un vecteur de pointeur et non pas un pointeur sur matrice !

Dernière modification par zephyre123 (Le 26/09/2020, à 21:34)

Hors ligne

#4 Le 26/09/2020, à 22:20

kamaris

Re : Deux programmes différents qui font exactement la même chose ?[RESOLU]

C'est parce que dans le premier cas, tu utilises une variable globale, ce qui change la manière dont la mémoire est allouée.
Si tu remplaces la matrice locale m par la matrice globale du premier cas, tu vas voir que ton initialisation ne marche pas non plus, mais sans plantage.
Sachant que dans ce cas, il ne faut pas juste déclarer matrice m; comme variable globale, car elle va être initialisée à 0, et tu ne vas rien voir du tout : il faut prendre la matrice initialisée avec des valeurs différentes de 0 du premier cas.

Bref, il y a plein de cas ou l'allocation est faite comme ci ou comme ça, selon le type, l'emplacement de la variable, la machine : ce qu'il faut, c'est écrire les choses correctement pour qu'elles aient un sens, qu'elles fonctionnent et qu'on sache pourquoi smile

Dernière modification par kamaris (Le 26/09/2020, à 22:22)

Hors ligne

#5 Le 27/09/2020, à 13:21

zephyre123

Re : Deux programmes différents qui font exactement la même chose ?[RESOLU]

Effectivement  les deux programmes fonctionnent car la variable matrice est globale j'ai fait les deux programmes suivants ;

Matrice déclarée en tant que variable globale :

#include <stdio.h>
#include <stdlib.h>


// Variable GLOBALE
int matrice[2][3] =
{
	{1, 2, 3},
	{4, 5, 6},
};

void initialisation(int (*pMatrice)[2][3])
{
	for(int i = 0; i < 2; i++)
		for(int j = 0; j < 3; j++)
			*pMatrice[i][j] = 0;

	for(int i = 0; i < 2; i++)
		for(int j = 0; j < 3; j++)
			printf("pMatrice[%d][%d] = %d\n",i, j, *pMatrice[i][j]);
}

int main(void)
{

	initialisation(&matrice);

	return EXIT_SUCCESS;
}

Puis j'ai fait le même code mais cette fois ci je n'ai pas déclarée matrice en tant que variable globale :

#include <stdio.h>
#include <stdlib.h>


void initialisation(int (*pMatrice)[2][3])
{
	for(int i = 0; i < 2; i++)
		for(int j = 0; j < 3; j++)
			*pMatrice[i][j] = 0;

	for(int i = 0; i < 2; i++)
		for(int j = 0; j < 3; j++)
			printf("pMatrice[%d][%d] = %d\n",i, j, *pMatrice[i][j]);
}

int main(void)
{

	int matrice[2][3] =
	{
		{1, 2, 3},
		{4, 5, 6},
	};

	initialisation(&matrice);

	return EXIT_SUCCESS;
}

Dans ce dernier cas j'ai bien un plantage avec l'erreur suivante :
*** stack smashing detected ***: <unknown> terminated
Abandon (core dumped)

Mais je ne comprends pas pourquoi ?
Es ce que t'as une explication kamaris ?

Hors ligne

#6 Le 27/09/2020, à 22:33

kamaris

Re : Deux programmes différents qui font exactement la même chose ?[RESOLU]

Il y a un niveau de détails où je ne serais pas capable de descendre à la volée, et j'avoue que j'ai la flemme de chercher la réponse très précise à cette question big_smile
Mais l'idée c'est que lorsque tu utilises une variable globale, l'espace alloué est plus important et que tu peux donc taper autour de la variable en réalisant des opérations qui restent « licites », ce qui n'est pas le cas avec une variable locale.

Voici un peu de lecture pour approfondir :
- Les différentes zones mémoire et leurs spécificités (n'hésite pas à consulter la version anglaise si la langue n'est pas un problème) : https://fr.wikipedia.org/wiki/Segment_de_donn%C3%A9es
- D'autres liens et réponses relatives aux zones mémoire : https://stackoverflow.com/questions/930 … in-c-and-c
- Un petit exemple de question similaire sur la taille allouée dans différents cas : https://stackoverflow.com/questions/119 … -variables
- Une petite expérience que tu peux faire en jouant sur les options de compilation pour passer du « warning » ci-dessus à un segmentation fault : https://stackoverflow.com/questions/134 … g-detected

Hors ligne

#7 Le 29/09/2020, à 18:41

NicoApi73

Re : Deux programmes différents qui font exactement la même chose ?[RESOLU]

Bonjour,

Les variables locales sont allouées sur la pile. Il y a un mécanisme d'identification de débordement de pile dans gcc qui génère ce message puisque effectivement ton code entraîne un débordement de pile. Ce n'est pas le cas avec une variable globale initialisée, puisque celle-ci est allouée dans le segment de données.

Si tu linkes avec l'option -fno-stack-protector, l'erreur ne sera plus détectée, comme dans le cas d'une variable globale. Mais tu jardines toujours en mémoire, tu n'initialises pas toutes tes données et donc tu t'exposes à un plantage.

Avec ton code utilisant une variable locale et l'option -fno-stack-protector

#include <stdio.h>
#include <stdlib.h>

void initialisation(int (*pMatrice)[2][3])
{
	for(int i = 0; i < 2; i++)
		for(int j = 0; j < 3; j++)
			*pMatrice[i][j] = 0;

	printf("--------------------\nInitialisation\n--------------------\n");
	for(int i = 0; i < 2; i++)
		for(int j = 0; j < 3; j++)
			printf("pMatrice[%d][%d] = %d\n",i, j, *pMatrice[i][j]);
}

int main(void)
{
	int matrice[2][3] =
{
	{1, 2, 3},
	{4, 5, 6},
};
	
	initialisation(&matrice);

	printf("--------------------\nFonction main apres init\n--------------------\n");
	for(int i = 0; i < 2; i++)
		for(int j = 0; j < 3; j++)
			printf("matrice[%d][%d] = %d\n",i, j, matrice[i][j]);

	return EXIT_SUCCESS;
}
--------------------
Initialisation
--------------------
pMatrice[0][0] = 0
pMatrice[0][1] = 0
pMatrice[0][2] = 0
pMatrice[1][0] = 0
pMatrice[1][1] = 0
pMatrice[1][2] = 0
--------------------
Fonction main apres init
--------------------
matrice[0][0] = 0
matrice[0][1] = 2
matrice[0][2] = 3
matrice[1][0] = 0
matrice[1][1] = 5
matrice[1][2] = 6


------------------
(program exited with code: 0)
Press return to continue

Hors ligne

#8 Le 04/10/2020, à 14:44

zephyre123

Re : Deux programmes différents qui font exactement la même chose ?[RESOLU]

Ok merci NicoApi73 pour ces précisons !
Retenir qu'il faut éviter le jardinage !
Merci encore pour toutes ces précisions.

Hors ligne