Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Problème de redéfinition difficile à résoudre...

6 réponses
Avatar
Eddahbi Karim
Salut,

J'ai chang=E9 mon client de news (j'ai fait des test sur fr.test, avec
PAN =E7a donnait n'importe quoi).

Pour en venir =E0 mon probl=E8me de C, voici mon code (sans la majorit=E9 d=
es
commentaires) :

/* Fichier args.c */

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

#include "include/args.h"


#define FIRST_DIM_SIZE(array) (sizeof((array))/sizeof ((*(array))))

int
check_parameter( char *param, int *argc )
{ =20
/* The program status */
int err =3D EXIT_FAILURE;
=20
/* The array index */
unsigned int i =3D 0;
=20
/* DEBUG : Check the pointers */
assert (param !=3D NULL && argc !=3D NULL);
=20
/* If no parameter is given, abort now */
if ( *argc < 1 )
{
(void) fprintf(stderr, "No parameters given. "
"Try --help for more information");
err =3D EXIT_FAILURE;
}
=20
/* If it's not a parameter, it's Ok */
else if ( *param !=3D '-' )
{
err =3D EXIT_SUCCESS;
}
=20
else /* It's a parameter */
{
=20
/* We check if the parameter is valid */
for ( i =3D 0; i < FIRST_DIM_SIZE(valid_params_s)
&& err !=3D EXIT_SUCCESS; i++ )
{
=20
/* If the argument is valid, stop the loop */
if ( strcmp(valid_params_s[i].name, param) =3D=3D 0 )
{
err =3D EXIT_SUCCESS;
/* i will be increase when the loop will finish.
We must decrease it to keep the current value */
i =3D i - 1;
}
=20
}
=20
/* If the parameter is valid :
Does the user gives enough argument for this parameter */ =20
=20
if ((err =3D=3D EXIT_SUCCESS) &&
(*argc - valid_params_s[i].args_needed < 1))
{
=20
(void) fprintf(stderr, "Too few arguments for %s. "
"Try --help for more information.\n"
,valid_params_s[i].name);
err =3D EXIT_FAILURE;
=20
}
=20
}
=20
=20

return err; =20
}


/* Fichier main.c */

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

#include "include/args.h"

int main ( int argc, char **argv )
{
/* Program status */
int err =3D EXIT_SUCCESS;

/* Wipe the name. I'll write a function that does this job */
{
=20
--argc;
++argv;
=20
}

/* Check the parameters entered */
for (; argc !=3D 0 && err !=3D EXIT_FAILURE;) =20
{
err =3D check_parameter( *argv, &argc );
=20
/* We jump to the next argument, only if everything is ok */
if ( err !=3D EXIT_FAILURE )
{
argc =3D argc - 1;
argv =3D argv + 1;
}
=20
}
=20
return err;
}

/* Fichier include/args.h */

#ifndef ARGS_H_INCLUDED

#define ARGS_H_INCLUDED 1

struct parameters {
char *name;
int args_needed;
} valid_params_s[] =3D
{
{"--help" , 0},
{"--version", 2},
{"-h" , 0},
{"-v" , 0}
};

extern int
check_parameter( char *param, int *argc );

#endif /* ARGS_H_INCLUDED */

Et le probl=E8me est que lorsque je veux compiler le programme en entier,
il me dit :

main.o(.data+0x0): multiple definition of `valid_params_s'
args.o(.data+0x0): first defined here

Pourtant j'ai d=E9fini une macro pour pas que args.h soit integr=E9 deux
fois.

Que faire ? Car je voudrais appeler cette structure dans d'autres
fichiers sources (avec les m=EAmes valeurs) mais =E9viter ce probl=E8me de
multiples d=E9finitions.

Voil=E0, si quelqu'un a une id=E9e.

--=20
--
ThE_TemPLaR

6 réponses

Avatar
Bertrand Mollinier Toublet
Eddahbi Karim wrote:
Pour en venir à mon problème de C, voici mon code (sans la majorité des
commentaires) :

<snip>

Et le problème est que lorsque je veux compiler le programme en entier,
il me dit :

main.o(.data+0x0): multiple definition of `valid_params_s'
args.o(.data+0x0): first defined here

Pourtant j'ai défini une macro pour pas que args.h soit integré deux
fois.

C'est pas pareil. args.h n'est inclus qu'une fois, mais dans deux unites

de compilation differentes. La macro dont tu te sers permet de s'assurer
que args.h ne soit inclus qu'une fois *dans une unite de compilation
donnee*.

Que faire ? Car je voudrais appeler cette structure dans d'autres
fichiers sources (avec les mêmes valeurs) mais éviter ce problème de
multiples définitions.

Voilà, si quelqu'un a une idée.

Oui, bin c'est normal. Prenons un exemple simplifie, mais qui illustre

ton probleme:

/* foo.c */

#include "baz.h"

/* fin foo.c */

/* bar.c */

#include "baz.h"

/* fin bar.c */

/* baz.h */
#ifndef BAZ_H
#define BAZ_H

int baz = 1;

#endif
/* fin baz.h */

J'espere que tu m'accorderas que ca reproduit exactement ton probleme.
Maintenant, regarde ce qui se passe apres le passage du preprocesseur:

/* foo.E */
int baz = 1;
/* fin foo.E */

/* bar.E */
int baz = 1;
/* fin bar.E */

Forcement, quand tu vas compiler et essayer de lier les deux objets, le
linker va se plaindre et te faire remarquer que tu as deux objets
distincts (puisqu'on leur a reserve de la memoire automatique dans les
deux unites de compilation) qui portent le meme nom. Ca marche pas.

Il faut que dans une de tes unites de compilation, baz soit declare
comme etant externe, alors que dans l'autre il soit defini comme valant
1. Il y a une methode moitie propre de faire ca avec un seul fichier
d'include:

/* baz.h */
#ifndef BAZ_H
#define BAZ_H

#ifdef DEFINE_BAZ
#define EXT
#else
#define EXT extern
#endif

EXT int baz
#ifdef DEFINE_BAZ
= 1
#endif
;

#endif
/* fin baz.h */

/* bar.c */
#include "baz.h"
/* fin bar.c */

/* foo.c */
#define DEFINE_BAZ
#include
#undef DEFINE_BAZ
/* fin foo.c */

De cette facon, tu definis baz une seule fois, peut-etre dans un fichier
qui a une relation speciale avec baz, et partout ailleurs, tu te
contentes de le declarer.
--
Bertrand Mollinier Toublet
Currently looking for employment in the San Francisco Bay Area
http://www.bmt.dnsalias.org/employment

Avatar
Eddahbi Karim
On Tue, 14 Oct 2003 16:48:24 -0700
Bertrand Mollinier Toublet r> wrote:

C'est pas pareil. args.h n'est inclus qu'une fois, mais dans deux unites
de compilation differentes. La macro dont tu te sers permet de s'assurer
que args.h ne soit inclus qu'une fois *dans une unite de compilation
donnee*.



Ok.

[snip l'exemple]


J'espere que tu m'accorderas que ca reproduit exactement ton probleme.


Vi vi :)

Maintenant, regarde ce qui se passe apres le passage du preprocesseur:

/* foo.E */
int baz = 1;
/* fin foo.E */

/* bar.E */
int baz = 1;
/* fin bar.E */

Forcement, quand tu vas compiler et essayer de lier les deux objets, le
linker va se plaindre et te faire remarquer que tu as deux objets
distincts (puisqu'on leur a reserve de la memoire automatique dans les
deux unites de compilation) qui portent le meme nom. Ca marche pas.


Donc il nous faut du scotch :D


Il faut que dans une de tes unites de compilation, baz soit declare
comme etant externe, alors que dans l'autre il soit defini comme valant
1. Il y a une methode moitie propre de faire ca avec un seul fichier
d'include:


[snip la méthode à moitié propre]

Ouais... Finalement définir deux fois la structure, c'est pas si mal hein ? :)
Je mettrais du scotch une autre fois


De cette facon, tu definis baz une seule fois, peut-etre dans un fichier
qui a une relation speciale avec baz, et partout ailleurs, tu te
contentes de le declarer.


Oki merci beaucoup :)

--
Bertrand Mollinier Toublet
Currently looking for employment in the San Francisco Bay Area
http://www.bmt.dnsalias.org/employment


<HS>
Ben voilà c'est ça de vouloir aller à San Francisco...
Pas taper, pas tapeeer !
</HS>
--
ThE_TemPLaR

Avatar
jean-marc
"Eddahbi Karim" wrote in message
news:
Salut,

J'ai changé mon client de news (j'ai fait des test sur fr.test, avec
PAN ça donnait n'importe quoi).

Pour en venir à mon problème de C, voici mon code (sans la majorité des
commentaires) :

/* Fichier args.c */

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

#include "include/args.h"


#define FIRST_DIM_SIZE(array) (sizeof((array))/sizeof ((*(array))))

int
check_parameter( char *param, int *argc )
{
/* The program status */
int err = EXIT_FAILURE;

/* The array index */
unsigned int i = 0;

/* DEBUG : Check the pointers */
assert (param != NULL && argc != NULL);

/* If no parameter is given, abort now */
if ( *argc < 1 )
{
(void) fprintf(stderr, "No parameters given. "
"Try --help for more information");
err = EXIT_FAILURE;
}

/* If it's not a parameter, it's Ok */
else if ( *param != '-' )
{
err = EXIT_SUCCESS;
}

else /* It's a parameter */
{

/* We check if the parameter is valid */
for ( i = 0; i < FIRST_DIM_SIZE(valid_params_s)
&& err != EXIT_SUCCESS; i++ )
{

/* If the argument is valid, stop the loop */
if ( strcmp(valid_params_s[i].name, param) == 0 )
{
err = EXIT_SUCCESS;
/* i will be increase when the loop will finish.
We must decrease it to keep the current value */
i = i - 1;
}

}

/* If the parameter is valid :
Does the user gives enough argument for this parameter */

if ((err == EXIT_SUCCESS) &&
(*argc - valid_params_s[i].args_needed < 1))
{

(void) fprintf(stderr, "Too few arguments for %s. "
"Try --help for more information.n"
,valid_params_s[i].name);
err = EXIT_FAILURE;

}

}



return err;
}


/* Fichier main.c */

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

#include "include/args.h"

int main ( int argc, char **argv )
{
/* Program status */
int err = EXIT_SUCCESS;

/* Wipe the name. I'll write a function that does this job */
{

--argc;
++argv;

}

/* Check the parameters entered */
for (; argc != 0 && err != EXIT_FAILURE;)
{
err = check_parameter( *argv, &argc );

/* We jump to the next argument, only if everything is ok */
if ( err != EXIT_FAILURE )
{
argc = argc - 1;
argv = argv + 1;
}

}

return err;
}

/* Fichier include/args.h */

#ifndef ARGS_H_INCLUDED

#define ARGS_H_INCLUDED 1

struct parameters {
char *name;
int args_needed;
} valid_params_s[] {
{"--help" , 0},
{"--version", 2},
{"-h" , 0},
{"-v" , 0}
};

extern int
check_parameter( char *param, int *argc );

#endif /* ARGS_H_INCLUDED */

Et le problème est que lorsque je veux compiler le programme en entier,
il me dit :

main.o(.data+0x0): multiple definition of `valid_params_s'
args.o(.data+0x0): first defined here

Pourtant j'ai défini une macro pour pas que args.h soit integré deux
fois.

Que faire ? Car je voudrais appeler cette structure dans d'autres
fichiers sources (avec les mêmes valeurs) mais éviter ce problème de
multiples définitions.

Voilà, si quelqu'un a une idée.

--
--
ThE_TemPLaR

Hello,

il n'y a qu'une seule bonne raison pour déclarer une variable dans un
header:
c'est si tu veux bruler en enfer pour toujours.

Jean-Marc
Avatar
Eddahbi Karim
On Wed, 15 Oct 2003 13:25:26 +0200
"jean-marc" wrote:

Hello,

il n'y a qu'une seule bonne raison pour déclarer une variable dans un
header:
c'est si tu veux bruler en enfer pour toujours.

Jean-Marc





Il n'y qu'une seule bonne raison de quoter plus de 200 lignes pour ajouter ça :
c'est si tu veux bruler en enfer pour toujours

:-D

Sinon j'ai compris ;)

En passant change ton lecteur de news pour qu'il ajoute des ">" à coté de ce que tu quotes :)

--
--
ThE_TemPLaR

Avatar
Bertrand Mollinier Toublet
Bertrand Mollinier Toublet wrote:
Il faut que dans une de tes unites de compilation, baz soit declare
comme etant externe, alors que dans l'autre il soit defini comme valant
1. Il y a une methode moitie propre de faire ca avec un seul fichier
d'include:

/* baz.h */
#ifndef BAZ_H
#define BAZ_H

#ifdef DEFINE_BAZ
#define EXT
#else
#define EXT extern
#endif

EXT int baz
#ifdef DEFINE_BAZ
= 1
#endif
;

#endif
/* fin baz.h */

/* bar.c */
#include "baz.h"
/* fin bar.c */

/* foo.c */
#define DEFINE_BAZ
#include
#undef DEFINE_BAZ
/* fin foo.c */

De cette facon, tu definis baz une seule fois, peut-etre dans un fichier
qui a une relation speciale avec baz, et partout ailleurs, tu te
contentes de le declarer.


Pour la petite histoire, la derniere fois que j'ai utilise cette
technique, c'etait il y a deux ans (ca explique certainement des choses)
alors que j'etais en stage chez C-Cube. Hier soir, j'ai vu un pote qui
bosse toujours dans la boite, et qui bosse toujours sur le meme produit
et qui a pour mission (debile) de passer tout leur code a la moulinette
de Splint. Incidement, il m'a fait remarque que Splint ralait a mort sur
un fichier que j'avais ecris, et bien evidement, c'etait celui ou
j'avais utilise la technique a la mords-moi-le-noeud.

Si la prochaine fois que vous jouez votre DVD avec le son en dts 5.1
vous avez des problemes, vous saurez a qui vous en prendre :-)

--
Bertrand Mollinier Toublet
[A] Top-posting.
[Q] What's the most annoying thing on Usenet ?

Avatar
Eddahbi Karim
On Wed, 15 Oct 2003 08:07:49 -0700
Bertrand Mollinier Toublet r> wrote:

Pour la petite histoire, la derniere fois que j'ai utilise cette
technique, c'etait il y a deux ans (ca explique certainement des choses)
alors que j'etais en stage chez C-Cube. Hier soir, j'ai vu un pote qui
bosse toujours dans la boite, et qui bosse toujours sur le meme produit
et qui a pour mission (debile) de passer tout leur code a la moulinette
de Splint. Incidement, il m'a fait remarque que Splint ralait a mort sur
un fichier que j'avais ecris, et bien evidement, c'etait celui ou
j'avais utilise la technique a la mords-moi-le-noeud.

Si la prochaine fois que vous jouez votre DVD avec le son en dts 5.1
vous avez des problemes, vous saurez a qui vous en prendre :-)



Ça tombe bien je n'ai pas de DVD :D.

En passant splint rale plutot pour n'importe quoi, surtout quand on s'amuse avec la gestion de mémoire sans programmation structurée.

--
--
ThE_TemPLaR