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 :

[Pointeurs] Incompatible type of assignment


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Inactif   Avatar de Deallyra
    Profil pro
    Étudiant
    Inscrit en
    Février 2007
    Messages
    1 997
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2007
    Messages : 1 997
    Par défaut [Pointeurs] Incompatible type of assignment
    Bonjour,

    Je suis à réaliser une petite application en client/serveur (1/1) qui doit me permettre d'envoyer des informations concernant un bilan fonctionnel pour obtenir des ratios.

    Partie gestion financière mise à part, j'ai un problème parce que je n'arrive pas à passer un tableau à une fonction puis à le récupérer.

    A la base, j'avais fait mon code comme un gros paquet d'instruction... Un point d'entrée main et voilà

    J'ai donc souhaité faire des fonctions afin de découper mon code en bloc lisibles et compréhensibles... Ce que j'essaie de faire mais j'ai énormément de mal avec la notion de pointeurs et références en C...

    Voici mon code :
    -- une archive se trouve à la fin du message

    Code C : 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
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
     
    /*************************************************
    ** Nom du fichier : client.h
    ** Deallyra
    **
    ** Entête de l'application cliente de calcul des
    **      différents ratios à partir du bilan fonctionnel.
    **
    *****************************************************/
     
    /**
     * Fonction de vérification de passage d'une adresse IP à l'application via
     *      le paramètre argv.
     * Dans le cas où le paramètre fourni ne serait pas une IP, l'application se
     *      termine.
     *
     * Non utilisée, nom du serveur servant à la connexion
     *
     *@param char
     *@return void
     */
    //void verifierCommandeLancement(char*);
     
    /**
     * Fonction de requête de saisie des différentes valeurs du Bilan fonctionnel
     *@param int
     *@return int
     */
    int bilan (int);
     
     
    // @todo
    /**
     * Fonction de création et connexion d'un socket entre deux stations
     *@param int
     *@return void
     */
    void creationConnexionSocket (int);
     
     
    /**
     * Fonction de requête de saisie des différentes valeurs du Bilan fonctionnel
     *@param long*
     *@return long*
     */
    long* saisieBilan(long*);

    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
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    /*************************************************
    ** Nom du fichier : client.c
    ** Deallyra
    **
    ** Fichier corps de l'application cliente de calcul des
    **      différents ratios à partir du bilan fonctionnel.
    **
    *****************************************************/
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    /* 
    #include <linux/types.h>
    #include <sys/socket.h>
    */
    #include <netdb.h>
     
     
    #include "client.h"
     
    //Port d'écoute du serveur
    #define PORT 20000
    //Taille maximale pour l'envoi des données d'un socket
    #define MAX_LENGTH 256
     
     
    /**
     * Fonction de vérification de passage d'une adresse IP à l'application via
     *      le paramètre argv.
     * Dans le cas où le paramètre fourni ne serait pas une IP, l'application se
     *      termine.
     *
     * Non utilisée, nom du serveur servant à la connexion
     *
     *@param char
     *@return void
     */
    /*void verifierCommandeLancement(char* adresseIP)
    {
    		 * /!\
    		 * Il faudrait vérifier l'IP autrement qu'en la parsant.
    		 * regexp possible en C ?
    		 *
     
    		//On indique la position du caractère par rapport à la "chaine" de l'IP.
    		int i = 0;
    		//Simulation d'un type booléen. 0=> False; 1=> True;
    		int estUneAdresseIP = 1;
     
    		//On vérifie les octets.
    		while(estUneAdresseIP == 1 && i <= 14)
    		{
    			//On récupère un octet.
    			int octet = adresseIP[i]*100+adresseIP[i+1]*10+adresseIP[i+2];
     
    			//Est-il compris entre 0 et 255 ?
    			if(octet <= 0 || octet >= 255)
    			{
    				estUneAdresseIP = 0;
    			}
     
    			i += 4;
    		}
     
    		//On vérifie les séparateurs (points) entre les octets.
    		i = 3;
    		while(estUneAdresseIP == 1 && i <= 11)
    		{
    			//Est-il compris entre 0 et 255 ?
    			if(strcmp(adresseIP[i], ".") != 0)
    			{
    				estUneAdresseIP = 0;
    			}
    			i += 4;
    		}
     
    		//Si le paramètre fourni n'est pas correct, l'application se termine.
    		if(estUneAdresseIP == 0)
    		{
    			perror( ">> Il faut fournir une adresse IP a l'application" );
    			exit( 1 );
    		}
    }
    */
     
    /**
     * Fonction de saisie des éléments du bilan fonctionnel
     *@param int
     *@return int
     */
    long* saisieBilan(long* input)
    {
     
    	printf( "\n\tETABLISSEMENT DU BILAN FONCTIONNEL\n\n" );
    	printf( "(Veuillez entrer les montants)\n" );
     
    	//Saisie des différentes valeurs de l'actif et du passif
    	printf( "\n- Actif -\n" );
    	printf( "Emplois Stables: " ); scanf( "%ld", &input[0] );
    	printf( "Actifs Circulants d'Exploitation: " ); scanf( "%ld", &input[1] );
    	printf( "Actifs Circulants Hors Exploitation: " ); scanf( "%ld", &input[2] );
    	printf( "Trésorerie de l'Actif: " ); scanf( "%ld", &input[3] );
    	printf( "\n- Passif -\n" );
    	printf( "Ressources Stables: " ); scanf( "%ld", &input[4] );
    	printf( "Dettes d'Exploitation: " ); scanf( "%ld", &input[5] );
    	printf( "Dettes Hors Exploitation: " ); scanf( "%ld", &input[6] );
    	printf( "Trésorerie du Passif: " ); scanf( "%ld", &input[7] );
     
    	return input;
    }
     
    /**
     * Fonction de requête de saisie des différentes valeurs du Bilan fonctionnel
     *@param int
     *@return int
     */
    int bilan(int sock)
    {
    	//Variable recevant les données à envoyer au serveur.
    	char data[MAX_LENGTH];
     
    	//Tableau recevant les différentes saisies du Bilan Fonctionnel
    	long input[8];
     
    	//Appel à la fonction de saisie du bilan
    	input = saisieBilan(input);
     
     
     
    	//Envoi des données au serveur
     
    	//Longueur de la donnée à envoyer || Sert de vérification également
    	int dataLength = 0;
     
    	//On "ré-initialise" la variable data à vide.
    	strcpy( data, "" );
     
    	//Pour chacune des données (du tableau) à envoyer
    	int i = 0;
    	while((i < 8) && (dataLength != -1) && (strcmp( data, "ERROR" ) != 0))
    	{
    		//On place la donnée dans la variable tampon data
    		sprintf( data, "%ld", input[i] );
    		//Si l'écriture dans le socket ne se passe pas bien
    		if (write( sock, data, strlen( data ) ) == -1)
    		{
    			perror( ">> Erreur: la fonction write() a renvoye une erreur." );
    			dataLength = -1;
    		}
    		//La donnée est transmise au serveur
    		else
    		{
    			//On attend l'accusé de réception du serveur
    			dataLength = read( sock, data, sizeof( char[MAX_LENGTH] ) );
    			//Tant que l'on ne reçoit rien, on continue à attendre la réponse du serveur.			
    			while (dataLength == 0)
    			{
    				dataLength = read( sock, data, sizeof( char[MAX_LENGTH] ) );
    			}
     
    			//Nous n'avons pas pu lire la réponse du serveur
    			if (dataLength == -1)
    			{
    				perror( ">> Erreur: la fonction read() a renvoye une erreur." );
    			}
    		}
    		i++;
    	}
     
    	//La fonction write() ou read() a envoyé une erreur.
    	//Le traitement n'a pas été à terme
    	if (dataLength != -1)
    	{
    		perror( ">> Erreur: le serveur a renvoye une erreur." );
    		exit( 1 );
    	}
    	else
    	{
    		printf( "\n\tResultat des calculs\n\n" );
    		//On lit la réponse du serveur
    		while (read( sock, data, sizeof( char[MAX_LENGTH] ) ) > 0)
    		{
    			printf( "%s", data );
    		}
    		return 1;
    	}
    }
    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
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    /*************************************************
    ** Nom du fichier : main.c
    ** Deallyra
    **
    ** Entrée du programme de l'application cliente de calcul des
    **      différents ratios à partir du bilan fonctionnel.
    **
    *****************************************************/
     
    int main (int argc, char **argv)
    {
    	//Variable permettant de vérifier que le descripteur du soket est créé
    	int connectSocket;
     
    	//Structure permettant de préparer l'adressage de la machine distante (serveur)
    	struct sockaddr_in connectInfos;
    	//Structure permettant de récupérer des infos sur la machine distante (serveur)
    	struct hostent *serverInfos;
     
    	//Port d'écoute du serveur
    	#define PORT 20000
    	//Taille maximale pour l'envoi des données d'un socket
    	#define MAX_LENGTH 256
     
    	//Fonction non utilisée pour le moment
    	//verifierCommandeLancement(char argv[0]);
     
    	//Création du socket
    		// socket(int domaine, int type, int protocole);
    			//Domaine => Famille de protocole, IP dans notre cas
    			//Type => TCP (SOCK_STREAM) ou UDP (SOCK_DGRAM)
    			//Protocole => A zéro généralement
    	if ((connectSocket = socket( AF_INET, SOCK_STREAM, 0 )) == -1)
    	{
    		perror( ">> Erreur: impossible de creer le socket." );
    		exit( 1 );
    	}
     
    	//On récupère le nom du serveur, paramètre d'entrée de l'application
    	serverName = argv[1];
     
    	//Récupération des informations sur la machine distante (serveur)
    	if ((serverInfos = gethostbyname(serverName)) == NULL)
    	{
    		perror( ">> Erreur: impossible de recuperer des informations sur le serveur." );
    		exit( 1 );
    	}
     
    	//Famille du protocole et son port
    	bcopy( (char *)serverInfos->h_addr, (char *)&connectInfos.sin_addr, serverInfos->h_length);
    	connectInfos.sin_family = serverInfos->h_addrtype; // ou connectInfos.sin_family = AF_INET
    	connectInfos.sin_port = htons( PORT );             // htons permet de faire les conversions necessaires a la portabilite du code
     
    	//Connexion au serveur avant de faire les traitements
    	if (connect( connectSocket, (struct sockaddr *)&connectInfos, sizeof( struct sockaddr_in ) ) == -1)
    	{
    		perror( ">> Erreur: impossible de connecter le socket au serveur." );
    		exit( 1 );
    	}
     
    	//Etablissement du Bilan
    	bilan( connectSocket );
     
    	//On ferme le socket dont le descriptif est passé en paramètre
    	close( connectSocket );
     
    	return 0;
    }
    et voici le makefile
    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
    CC=gcc
    CFLAGS=-Wall -Wextra -O -Wstrict-prototypes -Wunreachable-code -g
    LDFLAGS=
    EXEC=chatTCP_client
    SRC= $(wildcard *.c)
    OBJ= $(SRC:.c=.o)
     
    all: $(EXEC)
     
    chatTCP_client: $(OBJ)
    	@$(CC) -o $@ $^ $(LDFLAGS)
     
    main.o: client.h
     
    %.o: %.c
    	@$(CC) -o $@ -c $< $(CFLAGS)
     
    .PHONY: clean mrproper
     
    clean:
    	rm -rf *.o
     
    mrproper: clean
    	rm -rf $(EXEC)
    Et donc mon erreur est la suivante :
    client.c: Dans la fonction «bilan» :
    client.c:127: erreur: incompatible types in assignment
    client.c:146: attention : déclaration implicite de la fonction « «write» »
    client.c:155: attention : déclaration implicite de la fonction « «read» »
    make: *** [client.o] Erreur 1
    Ce qui concerne les lignes suivantes :

    Code C : 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
    36
    37
    38
    39
    40
    41
    42
    43
     
    /**
     * Fonction de saisie des éléments du bilan fonctionnel
     *@param int
     *@return int
     */
    long* saisieBilan(long* input)
    {
     
    	printf( "\n\tETABLISSEMENT DU BILAN FONCTIONNEL\n\n" );
    	printf( "(Veuillez entrer les montants)\n" );
     
    	//Saisie des différentes valeurs de l'actif et du passif
    	printf( "\n- Actif -\n" );
    	printf( "Emplois Stables: " ); scanf( "%ld", &input[0] );
    	printf( "Actifs Circulants d'Exploitation: " ); scanf( "%ld", &input[1] );
    	printf( "Actifs Circulants Hors Exploitation: " ); scanf( "%ld", &input[2] );
    	printf( "Trésorerie de l'Actif: " ); scanf( "%ld", &input[3] );
    	printf( "\n- Passif -\n" );
    	printf( "Ressources Stables: " ); scanf( "%ld", &input[4] );
    	printf( "Dettes d'Exploitation: " ); scanf( "%ld", &input[5] );
    	printf( "Dettes Hors Exploitation: " ); scanf( "%ld", &input[6] );
    	printf( "Trésorerie du Passif: " ); scanf( "%ld", &input[7] );
     
    	return input;
    }
     
    /**
     * Fonction de requête de saisie des différentes valeurs du Bilan fonctionnel
     *@param int
     *@return int
     */
    int bilan(int sock)
    {
    	//Variable recevant les données à envoyer au serveur.
    	char data[MAX_LENGTH];
     
    	//Tableau recevant les différentes saisies du Bilan Fonctionnel
    	long input[8];
     
    	//Appel à la fonction de saisie du bilan
    	input = saisieBilan(input);
    (...)

    J'aimerai bien que l'on m'apprenne à pécher et que je comprenne enfin comment marche ces "adorables" pointeurs... J'ai beau lire cours et tuto je ne comprends pas...

    long* peut dire qu'on veut passer un tableau de long comme dire qu'on passe un pointeur vers un long... je la fais comment la différence ?

    C'est assez nébuleux pour moi...

    Merci à vous pour toute aide que vous pourrez m'aporter.

    PS : voici une archive du code source
    *Si la réponse vous convient, n'oubliez pas le tag
    *Exprimez vous dans un français correct; on prend le temps de vous lire, prenez le temps de bien écrire.
    *Et comment on interprète votre code? N'oubliez pas la balise!

    *Pour une mise en page simple avec des divs.
    *Pour faire des formulaires xHTML CSS.

  2. #2
    Membre émérite
    Avatar de Pouet_forever
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    671
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 671
    Par défaut
    Pour ce qui est de tes déclarations implicites, il faut que tu inclues :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #include <sys/types.h>
    #include <unistd.h>
    Ensuite, tu déclares un tableau input[8] donc là pas de problème.
    Le problème c'est que en faisant ça : input = saisieBilan(input);
    Tu tentes de modifier l'adresse de input, et comme input est déclaré en tant que tableau tu n'as pas le droit de modifier son adresse !

    Et puis, comme input est un tableau, hé bien tu modifies directement ce tableau dans ta fonction tu n'as pas besoin de renvoyer de valeur
    Du coup tu as juste à faire ça :


  3. #3
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    long* peut dire qu'on veut passer un tableau de long comme dire qu'on passe un pointeur vers un long... je la fais comment la différence ?
    Il faut savoir sur les relations entre pointeur et tableau que :

    Dans tout contexte où intervient le nom d'un tableau, excepté les deux seuls cas où il est associé aux opérateurs sizeof ou & (adresse de), le nom du tableau représente une adresse non modifiable, l'adresse du premier élément du tableau.

    En conséquence :

    - on ne peut jamais écrire tableau = quelque chose

    - si tu passes en argument d'une fonction le nom d'un tableau d'objets T, tu passes en fait l'adresse du premier élément du tableau. Le paramètre correspondant dans la fonction est donc toujours un pointeur (initialisé avec cette adresse), donc est du type T*.
    A partir de l'adresse du premier élément et du type du pointeur (qui apporte l'information sur la taille d'un élément du tableau), le compilateur ou le programmeur est apte à trouver l'adresse de tous les éléments du tableau, donc d'y accéder.

    - Comment la fonction fait-elle la différence entre le passage de l'adresse de début d'un tableau d'objets T ou de l'adresse d'un unique objet T ?
    Elle ne la fait pas. Autrement dit, la fonction ne sait pas (sauf si on le lui dit explicitement) le nombre d'éléments d'un tableau passé en paramètre (ni même si c'est un tableau).
    C'est donc au programmeur de savoir ce qu'il fait.
    Deux syntaxes sont possibles pour la déclaration de la fonction (hors la question des VLA) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ... fonc( T* tab)
    ... fonc(T tab[])
    Elles sont toutes deux équivalentes et dans les deux cas tab est un pointeur. (La deuxième notation n'implique pas que tab soit un tableau). Dans la deuxième forme, il est possible de mettre dans les [] une valeur, qui est royalement ignorée par le compilateur; il est donc préférable de ne rien mettre.

  4. #4
    Inactif   Avatar de Deallyra
    Profil pro
    Étudiant
    Inscrit en
    Février 2007
    Messages
    1 997
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2007
    Messages : 1 997
    Par défaut
    Merci à vous deux pour vos explications.

    Pour finir, j'en étais arrivée à la conclusion de Pouet_forever...

    Diogène, vos interventions sont, comme toujours, un réel plaisir à lire et j'espère réellement avoir compris comme il faut l'utilisation des pointeurs.

    Encor une fois, merci à vous,
    *Si la réponse vous convient, n'oubliez pas le tag
    *Exprimez vous dans un français correct; on prend le temps de vous lire, prenez le temps de bien écrire.
    *Et comment on interprète votre code? N'oubliez pas la balise!

    *Pour une mise en page simple avec des divs.
    *Pour faire des formulaires xHTML CSS.

Discussions similaires

  1. error: incompatible types in assignement
    Par Melwen dans le forum Débuter
    Réponses: 3
    Dernier message: 02/05/2010, 20h34
  2. Réponses: 4
    Dernier message: 25/02/2010, 17h14
  3. Incompatible types in assignment
    Par Spinoza23 dans le forum Débuter
    Réponses: 4
    Dernier message: 11/06/2008, 09h40
  4. error: incompatible types in assignment
    Par panda31 dans le forum C
    Réponses: 2
    Dernier message: 13/06/2006, 10h46
  5. Réponses: 4
    Dernier message: 05/12/2005, 19h24

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