Declaration d'un tableau en langage C

Fermé
basopro Messages postés 100 Date d'inscription vendredi 11 mars 2011 Statut Membre Dernière intervention 3 juin 2015 - 4 juil. 2011 à 18:18
basopro Messages postés 100 Date d'inscription vendredi 11 mars 2011 Statut Membre Dernière intervention 3 juin 2015 - 15 juil. 2011 à 19:54
Bonjour à tous .
je voudrais savoir si est possible de declarer un tableau avec une dimension indeterminée; autrement dire , un tableau dynamique dont on ne precise pas la dimension de sotre que l'IDE ne nous signale pas qu'il y a des erreurs .
Si possible , comment le faire ?
merci de me sortir de cette zone d'ombre.



A voir également:

4 réponses

Hxyp Messages postés 401 Date d'inscription vendredi 28 janvier 2011 Statut Membre Dernière intervention 27 avril 2014 54
4 juil. 2011 à 18:46
Bonjour,
Il faut utiliser les pointeurs, et leur donner l'adresse de la mémoire qu'on a allouer pour le tableau. Exemple pour un tableau de char
char *tableau; /* un pointeur */
tableau = malloc(sizeof(char)*20); /* on demande 20 char en mémoire */
/* tableau prend alors pour valeur l'adresse retournée par malloc */
if(tableau!=NULL) /* si l'opération à réussi tableau contient l'adresse des 20char  (l'adresse du premier bloc de la taille du type***) */
{
    /* alors on peut utiliser tableau comme un simple tableau ici par exemple */
}


pour changer la taille du tableau vous pouvez libérer la mémoire qui est à l'adresse qu'on a mis dans le pointeur avec free, puis refaire un malloc comme si de rien en utilisant une nouvelle taille pour récupérer une nouvelle adresse. Ou utiliser realloc...
Pouvez aussi utiliser calloc pour réserver de la mémoire et la mettre directement à zéro..

***l'adresse du premier bloc de la taille du type, ce qui fait par exemple pour :
char *tableau=malloc(sizeof(char)*4);
donne en mémoire :
[char1][char2][char3][char4]
et donc le pointeur "tableau" contient l'adresse de [char1] si on incrémente la Valeur de "tableau" (donc l'adresse) de sizeof(char) on tombe sur [char2] etc..

petit bout de code pour expliquer ça :
#include <stdio.h>
#include <stdlib.h>

int main(void)
  {
    char *tab=malloc(sizeof(char)*4); /* tab à l'adresse du premier bloc de la taille d'un char */
    tab+=sizeof(char); /* incrémente d'un char l'adresse contenu dans tab */
    *tab='x'; /* met la lettre x dans l'emplacement */
    tab-=sizeof(char); /* décrémente d'un char l'adresse contenu dans tab */
    *tab='z'; /* y met un z */
    printf("%s\n",tab);
    free(tab);
    return 0;
  }

ça affiche :
zx
1
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
4 juil. 2011 à 20:01
@Hxyp,
C'est plutôt tab+=1 (ou tab++) qu'il faut mettre que tab+=sizeof(char) pour décaler d'un élément (quel qu'il soit).
Ici effectivement, ça ne change rien car sizeof(char) vaut toujours 1, mais pour un autre type, ça ne marcherait pas.
Cdlt,
0
basopro Messages postés 100 Date d'inscription vendredi 11 mars 2011 Statut Membre Dernière intervention 3 juin 2015 1
5 juil. 2011 à 13:49
merci a vous .Merci de mavoir sortir de ce trou.
0
Hxyp Messages postés 401 Date d'inscription vendredi 28 janvier 2011 Statut Membre Dernière intervention 27 avril 2014 54
Modifié par Hxyp le 5/07/2011 à 20:18
@fiddy théoriquement ça marche en fait vu que les adresses sont décalées de la taille du type,

là avec un tableau de double et en utilisant à l'arrache un int pour calculer l'adresse :
#include <stdio.h> 
#include <stdlib.h> 

int main(void) 
  { 
    double *tab=malloc(sizeof(double)*4); 
    unsigned int i,ptr; 
    for(i=0;i<4;i++) 
        printf("tab[%d] =  %p\n",i,&tab[i]); 
    ptr=tab; 
    ptr+=sizeof(double); 
    printf("ptr+=sizeof(double) = %x\n",ptr); 
    tab=ptr; 
    *tab=3.14; 
    ptr-=sizeof(double); 
    printf("ptr-=sizeof(double) = %x\n",ptr); 
    tab=ptr; 
    *tab=2.21; 
    printf("tab[0] = %f %p\n",tab[0],&tab[0]); 
    printf("tab[1] = %f %p\n",tab[1],&tab[1]); 
    free(tab); 
    return 0; 
  } 
============== 
tab[0] =  0x804a008 
tab[1] =  0x804a010 décalage de 64bits 
tab[2] =  0x804a018 
tab[3] =  0x804a020 
ptr+=sizeof(double) = 804a010 
ptr-=sizeof(double) = 804a008 
tab[0] = 2.210000 0x804a008  
tab[1] = 3.140000 0x804a010 
ça fonctionne donc! 

Et là avec des short int :
#include <stdio.h> 
#include <stdlib.h> 

int main(void) 
  { 
    short int *a=malloc(sizeof(short int)*4); 
    int i; 
    for(i=0;i<4;i++) 
        printf("%p\n",&a[i]); 
    free(a); 
    return 0; 
  } 
============== 
0x804a008 
0x804a00a décalage de 16bits 
0x804a00c 
0x804a00e


Un autre avec une struct :
 
#include <stdio.h> 
#include <stdlib.h> 

struct plop{ 
    int a; 
    double b; 
    short int c; 
}; 

int main(void) 
  { 
    int i; 
    struct plop *test; 
    test=malloc(sizeof(struct plop)*4); 
    printf("sizeof(struct plop) = %d bits\n",sizeof(struct plop)*8); 
    for(i=0;i<4;i++) 
        printf("%p\n",&test[i]); 
    free(test); 
    return 0; 
  } 
============== 
sizeof(struct plop) = 128 bits 
0x804a008 
0x804a018 décalage de 128 bits 
0x804a028 
0x804a038
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
Modifié par fiddy le 5/07/2011 à 21:06
Si tu veux argumenter en prenant un code, c'est une bonne idée. Par contre, il ne faut pas changer de périmètre...

Dans ta nouvelle version (voir ci-dessous), tu sauvegardes l'adresse du tableau tab dans une variable unsigned int. Bien sûr qu'après, il faut que tu incrémentes de sizeof(double) pour passer à la case d'après.
    double *tab=malloc(sizeof(double)*4);  
    unsigned int i,ptr;  
    ptr=tab; 
    ptr+=sizeof(double);  
    tab=ptr; 


Maintenant, je remets ton code initial :
 
    char *tab=malloc(sizeof(char)*4); 
    tab+=sizeof(char); 

Là tu incrémentes directement l'adresse du tableau. C'est très différent... C'est dans ce cas que je t'ai fait ma remarque : tab++; car si c'est sur un double, ça ne marchera pas.

Cdlt,
0
Hxyp Messages postés 401 Date d'inscription vendredi 28 janvier 2011 Statut Membre Dernière intervention 27 avril 2014 54
5 juil. 2011 à 21:15
Oui forcément j'ai dis théoriquement hahaha, à la base c'était pour expliquer le décalage des adresses mais c'est vrai que le premier exemple n'était pas terrible vu que ça se fait automatiquement lorsqu'on incrémente un pointeur, l'incrémentation (changement d'adresse) se fait en fonction du type du pointeur donc oui le premier exemple était relativement bidon,
enfin le code que j'ai donné ensuite détaille un peu mieux ce que je voulais dire.
L'erreur a été d'avoir incrémenté sur le pointeur directement, enfin je pense qu'on a tous compris la différence
0
Bonjour,

Tu as une réponse de Hxyp et fiddy qui t'explique comment allouer un tableau par malloc, mais leur réponse me paraît très générale et pas forcément
facilement réalisable par quelqu'un qui n'a pas une grosse pratique du C, c'est pourquoi je me permet d'ajouter ma réponse pour t'aider un peu plus :

Si ce que tu veux est un tableau qui grandit tout seul en fonction de ce qu'on y met, ça n'existe pas en C.
En C++ par contre oui (classes de STL Vector par exemple)
En java ou .net aussi avec les ArrayList ou Vector
Mais ceci est du au fait que ces 3 langages sont des langages objet contrairement au C.
Par contre, tu peut simuler ce fonctionnement grâce à l'allocation dynamique des tableaux en C :
Créer une structure MonTableau qui contient un pointeur sur le type de données souhaitées et la dernière taille allouée.
Créer un fonction qui s'appelle affecterDonnee(int indice,typedonnee donnee,MonTableau tableau)
Cette fonction va
- vérifier si l'indice est inférieur à la taille actuelle
- Si ce n'est pas le cas elle alloue un nouveau tableau de la taille + taille grossissement (growing en anglais)
- Toujours dans le cas où la taille était insuffisante, elle fait une copie des éléments de l'ancien tableau dans le nouveau tableau et modifie la taille indiquée dans la structure
- Dans tous les cas elle affecte la donnée pour l'indice concerné.
Évidemment, ce n'est pas très souple et on peut oublier d'appeler la fonction, mais ça fait partie des raisons d'existence des langages objets.
Pour être pragmatique, j'ai fais un petit programme qui démontre ce que j'avance, à toi de l'adapter à tes besoins.
Le problème c'est que le correcteur orthographique ne laisse pas passer alors que j'ai mis les balises code. Je ne comprends pas
Je vais essayer de le joindre dans un deuxième post, où sinon, si tu veux je te l'envoie en MP.
Cordialement
1
basopro Messages postés 100 Date d'inscription vendredi 11 mars 2011 Statut Membre Dernière intervention 3 juin 2015 1
12 juil. 2011 à 20:51
Salut java4ever , juste pour t'avouer que ta réponse ma sortir du trou et aussi ta manière de coder ma convaincu. Étant débutant je suis déjà un passionné de la programmation informatique et je souhaite avoir une bonne connaissance dans ce domaine .
J'aimerais donc savoir s'il est possible d'avoir votre contact (facebook ou mail ) pour vos demander quelques conseils de temps en temps.
merci de me comprendre et de me repondre.
Je recevrai votre eponse par dans ma boite mail.
0
basopro Messages postés 100 Date d'inscription vendredi 11 mars 2011 Statut Membre Dernière intervention 3 juin 2015 1
15 juil. 2011 à 19:54
Salut java4ever , juste pour t'avouer que ta réponse ma sortir du trou et aussi ta manière de coder ma convaincu. Étant débutant je suis déjà un passionné de la programmation informatique et je souhaite avoir une bonne connaissance dans ce domaine .
J'aimerais donc savoir s'il est possible d'avoir votre contact (facebook ou mail ) pour vos demander quelques conseils de temps en temps.
merci de me comprendre et de me repondre.
Je recevrai votre eponse par dans ma boite mail.
0
Bonjour, le code promis :
#include <stdio.h>
#include <stdlib.h>
/*****
  Exemple simplifié de tableau à grossissement automatique en C
  Date de création : 4 juillet 2011.
**/
typedef struct 
{
  int taille;
  long *elements;
  int taille_Grossissement;
} TableauDeLongs;

void affecterTableauDeLongs(TableauDeLongs *tab,long valeur, int index);

int main()
{
  TableauDeLongs montableau = {0, 0, 10}; // Mon tableau "intelligent" (si on l'aide un peu)
  // faire une boucle de saisie de nombre entiers et les mettre dans un tableau auto grossissant en C 
  printf("Saisir autant de nombres (entiers long) que souhaité : arrêt si on rentre le nombre 9999\n");
  long unnombre = 0;
  int indexsuivant = 0;
  do
  {
     printf("Saisir un nombre à mettre das le tableau : ");
	 scanf("%ld",&unnombre);
	 affecterTableauDeLongs(&montableau, unnombre, indexsuivant);
	 ++indexsuivant; // pour le prochain
  }
  while (unnombre != 9999);
  printf("Voici la liste des saisies stockées dans le tableau rangées par 5\n");
  int i,j;
  for (i = 0,j = 0;i < indexsuivant;++i,++j)
  {
      printf("\t%ld", montableau.elements[i]);
	  if (j < 4)
	  {
	    printf(", ");
	  }
	  else
	  {
	    j = -1;
	    printf("\n");
	  }
  }
}
// Gestion en C d'un grossissement de tableau "automatique" : l'index part de 0
void affecterTableauDeLongs(TableauDeLongs *tab,long valeur, int index)
{
  if (index < 0)
  {
    fprintf(stderr, "*****index negatif interdit*********\n");
	return;
  }
  printf("\nDemande affecter tableau[%d]\n", index);
  if (index >= tab->taille)
  {
     int nouvelle_taille;
     // calcul de la nouvelle taille en multiple de la taille de grossissement (on aurait pu utiliser la fonction ceil(), mais bon
     int nombre_unites = (index + 1)/tab->taille_Grossissement;
	 if (((index + 1) % tab->taille_Grossissement) != 0) nombre_unites += 1;
	 nouvelle_taille = nombre_unites * tab->taille_Grossissement;
	 printf("\n>>>>>>>>>Augmentation de la taille du tableau de %d à %d\n",tab->taille, nouvelle_taille);
	 // nouvelle allocation mémoire et récup des anciens éléments
	 // on pourrait utiliser realloc, mais ça me parait plus clair comme ça, et en plus on peut initialiser à 0 les nouvelles valeurs
	 long *nouveau_elements = calloc(nouvelle_taille,sizeof(long));
	 memset(nouveau_elements,0,nouvelle_taille * sizeof(long)); // met des 0 partout
	 memcpy(nouveau_elements, tab->elements, tab->taille*sizeof(long)); // copie de l'ancien tableau
	 if (tab->taille > 0)
	 {
	    free(tab->elements);
	 }
	 tab->elements = nouveau_elements; // remplace le tableau
	 tab->taille = nouvelle_taille;
  }
  tab->elements[index] = valeur;
}
0
basopro Messages postés 100 Date d'inscription vendredi 11 mars 2011 Statut Membre Dernière intervention 3 juin 2015 1
5 juil. 2011 à 13:55
merci pour ce service .merci de me sortir de ce trou

while (life=continue)
{
programmation vivra et revivra
}
0
periplasme Messages postés 391 Date d'inscription vendredi 22 avril 2011 Statut Membre Dernière intervention 5 février 2013 53
5 juil. 2011 à 09:52
après, on peux aussi utilisé les listes chainés ... c'est un peu plus chiant a utilisé qu'un tableau (quoi que, avec de l'entrainement, ça devient tout aussi naturel)
mais au final, on a un simili-tableau qui peux s'étendre quasi sans limite (juste celle de la mémoire disponible)
0
basopro Messages postés 100 Date d'inscription vendredi 11 mars 2011 Statut Membre Dernière intervention 3 juin 2015 1
5 juil. 2011 à 14:19
merci pour votre aide
0