IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Tableaux et pointeurs


Sujet :

C

  1. #1
    Inactif  
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    60
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 60
    Par défaut Tableaux et pointeurs
    Bonjour,

    J'ai un problème récurent:

    Dans mon cours, il est dit qu'il est possible de travailler avec des pointeurs mêmer pour des tableaux à plusieurs dimensions pour obtenir toutes les valeurs du tableau par incrémentation du pointeur auquel on a affecté la valeur du tableau (début de l'emplacement mémoire), car le poiteur était converti dans le type "type*".

    A chaque compilation sous visual C++, le message suivant apparait:

    c:\users\yonathan\documents\visual studio 2005\projects\40\40\source.cpp(17) : error C2664: 'somme'*: impossible de convertir le paramètre 1 de 'float [2][3]' en 'float *'
    1> Aucun contexte dans lequel cette conversion est possible

    Voici le code du programme qui est censé renvoyer la somme des élements d'un tableau fourni en argument:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
    #include <stdio.h>
     
    void main()
    {
    	float somme (float * t, int i, int j);
     
    	int i, j;
    	float t [2][3] = {1, 2, 3, 4, 5, 6};
     
    	for (i=0; i<2; i++)
    		for (j=0; j<3; j++)
    		{
    			printf("entrez valeur");
    			scanf("f", &t[i][j]);
     
    		}
    	somme(t, i, j);
    }
     
    float sommme (float * t, int i, int j)
    {
    	int nbr = i*j, k;
    	float somme;
     
    	int * adt;
    	adt = (float *) t;
     
    	for (k=0; k<nbr; k++)
    		somme += *(adt + k);
     
    	printf("somme : %f", somme);
     
    }

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    131
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 131
    Par défaut
    Deja dans le main :

    t est un pointeur de flottant (float *t) et non un pointeur de pointeur de flottant (float **t)!!!

    Puis dans somme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    float sommme (float * t, int i, int j) {
    ...
    }
    Ou est le return ?

    Tu dois caster t en (int *) car adt est un pointeur d entier.


    Tu devrais choisir soit d utiliser des flottants, soit des entiers mais pas les 2 en meme temps...

  3. #3
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    et oui c'est possible de faire ce que tu veux, mais par contre la notation ne devient pas tab[i][j] mais tab[i*largeur+j]...

    Si tu alloues en une seule fois (par exemple largeur*longueur), alors le pointeur désigne le début de l'espace adressé, et est considéré comme un tableau unidimensionnel.

    C'est donc à toi de faire l'adressage exact.

    C'est vrai que c'est en général plus pratique de coder comme ça (en général les images en C sont comme ça, les volumes également).

  4. #4
    Inactif  
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    60
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 60
    Par défaut
    Citation Envoyé par berg
    Deja dans le main :

    t est un pointeur de flottant (float *t) et non un pointeur de pointeur de flottant (float **t)!!!

    Puis dans somme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    float sommme (float * t, int i, int j) {
    ...
    }
    Ou est le return ?

    Tu dois caster t en (int *) car adt est un pointeur d entier.


    Tu devrais choisir soit d utiliser des flottants, soit des entiers mais pas les 2 en meme temps...

    Je n'ai pas compris pourquoi selon ce que j'ai écrit c'est un poiteur **f,
    et puis caster en int* ne m'aide pas puisque je travaille sur des données en float et j'ai besoin de fazire passer chaque fois le pointeur à la prochaine donnée float stockée en mémoire

  5. #5
    Inactif  
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    60
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 60
    Par défaut
    Citation Envoyé par souviron34
    et oui c'est possible de faire ce que tu veux, mais par contre la notation ne devient pas tab[i][j] mais tab[i*largeur+j]...

    Si tu alloues en une seule fois (par exemple largeur*longueur), alors le pointeur désigne le début de l'espace adressé, et est considéré comme un tableau unidimensionnel.

    C'est donc à toi de faire l'adressage exact.

    C'est vrai que c'est en général plus pratique de coder comme ça (en général les images en C sont comme ça, les volumes également).

    Merci de ta réponse,

    Je te cite mon cours:

    "..Un appel de notre fonction de fera ainsi
    int t[30][30];
    diag (t, 30);

    Or l'argument effectif t est certes, l'adresse de t, mais d'un type pointeur sur des blocs de 10 entiers et non pointeur sur des entiers. En fait, la présence d'un prototype pour diag fera qu'il sera convertien int *..........

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    131
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 131
    Par défaut
    Citation Envoyé par byonatane
    Je n'ai pas compris pourquoi selon ce que j'ai écrit c'est un poiteur **f,
    et puis caster en int* ne m'aide pas puisque je travaille sur des données en float et j'ai besoin de fazire passer chaque fois le pointeur à la prochaine donnée float stockée en mémoire

    Autant pour moi

    J ai regarde le float *t de

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void main()
    {
    	float somme (float * t, int i, int j);
    	....

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    131
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 131
    Par défaut
    De plus lorsque je compile voila ce que ca me donne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    titi.c: In function ‘main’:
    titi.c:17: warning: passing argument 1 of ‘somme’ from incompatible pointer type
    titi.c:4: warning: return type of ‘main’ is notint’
    titi.c: In function ‘sommme’:
    titi.c:26: warning: assignment from incompatible pointer type
    /tmp/ccOQfZ8d.o: In function `main':
    titi.c:(.text+0xb1): undefined reference to `somme'
    collect2: ld returned 1 exit status

    Une de tes erreurs vient de :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    float t [2][3] = {1, 2, 3, 4, 5, 6};
    tu declare une matrice mais tu l initialise comme si c etait un tableau a une dimension...

    Soit tu fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    float t [2][3] = {{1, 2, 3},{ 4, 5, 6}};
    Soit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    float t [6] = {1, 2, 3, 4, 5, 6};

  8. #8
    Inactif  
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    60
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 60
    Par défaut
    Il y a un trois m dans la définition de la fonction (sommme)

    A part ca ce n'est pas problématique de déclarer comme ça le tableau, les affectations sont faites automatiquement pour les dimensions du tableau - si l'on en croit mon livre

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    131
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 131
    Par défaut
    Je regarde mon K&R fraichement achete !!! (apres plusieurs annees me suis enfin decide a l acheter ) ... page 122 ... He oui tu as RAISON !!!!

    D ailleurs il n y a aucun warning a la ligne que j ai indique....
    Il est temps pour moi d aller me coucher

  10. #10
    Inactif  
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    60
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 60
    Par défaut
    moi je travaille dur le delannoy c'est pas mal bien que certaines personnes ici m'aient dit que ses livres sont mauvais,

    en tout cas on a toujours pas compris pourquoi le compilateur refuse de faire la conversion

  11. #11
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    Bon on va essayer de t'expliquer...

    D'abord on s'occupe des erreurs de C "bête" dans ton code :

    • pas de include <stdlib.h>
    • pas la bonne syntaxe de main (soit int main(void) soit int main (int argc, char **argv) )
    • pas le bon format dans le scanf (pas de %)
    • pas la bonne variable dans le scanf (il faut des parenthèses : &(t[i][j]) )
    • pas de return du main
    • pas besoin de la variable adt (et d'abord comme déjà dit pourquoi un int ?)
    • somme n’est pas initialisé, donc tu sommes sur quelque chose d’indéfini…
    • pas de retour du résultat alors que la déclaration de la fonction indique qu'elle retourne un float.



    Maitenant occupons-nous du problème tableau/pointeur ...

    Pour un tableau UNIDIMENSIONNEL, le nom du tableau est équivalent à l'adresse du premier élément, et donc le nom est équivalent à un pointeur.

    float t[6] ;

    t == &(t[0])

    Donc en déclarant un tableau UNIDIMENSIONNEL, on peut y référer dans l'appel d'une fonction par un pointeur..

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    float t[6] ;
     
    somme(t) ;
     
    void somme ( float *t)
    {
    }

    Mais là tu déclares un tableau BI-DIMENSIONNEL.

    t est donc un tableau de tableaux... donc le nom t n'est plus un pointeur sur un float, mais un pointeur sur un tableau de float

    Donc dans ce cas :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    float t[2][3] ;
     
    somme ( t[0] );
     
    somme ( float t[] )
    {
     float *p=t ;
    }
    est valide

    Maintenant, pour faire ce que tu veux de manière simple, il suffit de se rappeler que t n’étant que le nom d’un tableau de tableaux, ce n’est pas en utilisant t qu’on pointera sur le premier élément (t pointe sur t[0]), mais &(t[0][0]) .

    Ton code deviendra donc :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
     
    #include <stdlib.h>
    #include <stdio.h>
     
    int main(void)
    {
       float somme (float *t, int i, int j);
     
       int i, j;
       float t[2][3], f;
     
       for (i=0; i<2; i++)
         for (j=0; j<3; j++)
           {
    	 printf("entrez valeur\n");
    	 scanf("%f", &(t[i][j]));
           }
     
       f = somme(&(t[0][0]), i, j);
     
       return 0 ;
    }
     
    float somme (float *t, int i, int j)
    {
      int nbr = i*j, k;
      float somme=0.0;
     
      for (k=0; k<nbr; k++)
        somme += *(t + k);
     
      printf("somme : %f\n", somme);
     
      return somme ;
    }
    [EDIT]

    Je rajouterais, pour plus de compréhension, quelques extraits de K&R :

    5.3 Pointers and Arrays
    In C, there is a strong relationship between pointers and arrays, strong enough that pointers and arrays should be discussed simultaneously. Any operation that can be achieved by array subscripting can also be done with pointers. The pointer version will in general be faster but, at least to the uninitiated, somewhat harder to understand.
    et aussi :

    By definition, the value of a variable or expression of type array is the address of element zero of the array. Thus after the assignment
    pa =
    *pa and a have identical values. Since the name of an array is a synonym for the location of the initial element, the assignment pa=&a[0] can also be written as
    pa = a;
    There is one difference between an array name and a pointer that must be kept in mind. A pointer is a variable, so pa=a and pa++ are legal. But an array name is not a variable; constructions like a=pa and a++ are illegal.
    When an array name is passed to a function, what is passed is the location of the initial element. Within the called function, this argument is a local variable, and so an array name parameter is a pointer, that is, a variable containing an address.
    [/EDIT]

    Mais Emmanuel aura peut-être quelque chose de plus clair (si j'ai pas dit trop de bêtises)..

  12. #12
    Inactif  
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    60
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 60
    Par défaut
    Merci pour vos conseils

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Les tableaux de pointeurs char*
    Par Basmor dans le forum Débuter
    Réponses: 4
    Dernier message: 28/08/2009, 01h19
  2. tableaux de pointeurs sur tableaux
    Par Ashin dans le forum C++
    Réponses: 3
    Dernier message: 11/02/2009, 20h31
  3. Problème avec les tableaux de pointeurs
    Par TheDoci dans le forum C
    Réponses: 2
    Dernier message: 07/01/2007, 13h04
  4. allocation dynamique et tableaux de pointeurs
    Par gbardy dans le forum 4D
    Réponses: 3
    Dernier message: 06/07/2006, 11h08
  5. en COM Tableaux de pointeurs d'interface:
    Par Barahn dans le forum MFC
    Réponses: 11
    Dernier message: 30/09/2005, 16h42

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo