Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Je cale. Help !

1 view
Skip to first unread message

Pierre Maurette

unread,
Nov 29, 2006, 8:09:21 AM11/29/06
to
Bonjour,

Je tourne en rond depuis deux heures sur un problème qui doit être
évident. Code réduit qui plante (exception à l'exécution):

#include <stdio.h>
#include <stdbool.h>
#include <limits.h>

/*
#if !defined(__STDC__)
#error Standard ANSI C compiler required
#endif
*/


#if defined(__cplusplus)
#error C++ compiler not allowed
#endif

typedef struct
{
int serial;
int data;
unsigned long* ul;
}
coin;

unsigned long MoyenneCoins(coin* Debut, size_t nbr)
{
size_t indice;
unsigned long result = 0, dummy;
bool overflow = false;
for(indice = 0; !overflow && (indice < nbr); indice++)
{
dummy = result;
result += *((Debut + indice)->ul);
overflow = (result < dummy);
}
overflow = overflow && (result > ULONG_MAX / nbr);
puts(overflow ? "Overflow" : "OK");
return overflow ? ULONG_MAX : result / nbr;
}

#define TAILLE 4
int main()
{
coin tabCoin[TAILLE];
unsigned long testValue = UCHAR_MAX;
tabCoin[1].ul = &testValue;
tabCoin[2] = tabCoin[1];
tabCoin[3] = tabCoin[2];
printf("%lu\n", MoyenneCoins(tabCoin, TAILLE));
return 0;
}


Merci de m'aider...

--
Pierre Maurette


Stéphane Goujet

unread,
Nov 29, 2006, 8:13:24 AM11/29/06
to
Pierre Maurette a écrit :

> typedef struct
> {
> int serial;
> int data;
> unsigned long* ul;
> }
> coin;
> unsigned long MoyenneCoins(coin* Debut, size_t nbr)
> {
> for(indice = 0; !overflow && (indice < nbr); indice++)
> {
> dummy = result;
> result += *((Debut + indice)->ul);
> overflow = (result < dummy);
> }
> #define TAILLE 4
> int main()
> {
> coin tabCoin[TAILLE];
> unsigned long testValue = UCHAR_MAX;
> tabCoin[1].ul = &testValue;
> tabCoin[2] = tabCoin[1];
> tabCoin[3] = tabCoin[2];
> printf("%lu\n", MoyenneCoins(tabCoin, TAILLE));

tabCoin[0] n'est pas initialisé ?

A+,
Stéphane.

Pierre Maurette

unread,
Nov 29, 2006, 8:19:13 AM11/29/06
to

Damned, mais c'est bien sûr ! Il manque ul dans un coin... ;-)

Merci.

--
Pierre Maurette


Stéphane Goujet

unread,
Nov 29, 2006, 8:23:40 AM11/29/06
to
Pierre Maurette a écrit :

> Il manque ul dans un coin... ;-)

Ne me dites pas que vous avez écrit tout ce programme pour pouvoir
faire cette blague ? Non... Si ? Si ! Ah, l'affreux ! ;->

A+,
Stéphane.

Jean-Marc Bourguet

unread,
Nov 29, 2006, 8:39:01 AM11/29/06
to
Pierre Maurette <maurett...@wanadoo.fr> writes:

> #if defined(__cplusplus)
> #error C++ compiler not allowed
> #endif

Quel est l'objectif? Ça n'a un interet que si on a identifie l'utilisation
d'une difference de comportement entre le C et le C++ et qu'on l'indique.
Sinon, le seul effet est d'em... le pauvre type qui va devoir se tapper
l'ecriture d'un script pour pour virer ces lignes-la de tous les fichiers
quand il faudra compiler le code avec un compilateur C++. Murphy va
naturellement frapper et l'utilisation de ce script va faire manquer le
fichier unique ou la precaution etait necessaire et documentee.

A+

--
Jean-Marc

Pierre Maurette

unread,
Nov 29, 2006, 9:01:39 AM11/29/06
to

Je comprends que vous citiez Murphy, spécialiste de l'emmerdement
maximum.
Vous écrivez un film sur la destination d'un bout de code. Il s'agit
d'un modèle me servant à faire des tests, par exemple lors de la
fréquentation de fr.comp.lang.c, mais pas uniquement. J'utilise
Code::Blocks ou PSPad, et j'ai paramétré sous Windows une douzaine de
compilateurs, et ne les maîtrise pas tous. Il est important que je
puisse bricoler les options de construction, et il m'est arrivé,
rarement quand même, de compiler en C++ s'en m'en rendre compte, alors
que je voulais justement vérifier tel ou tel point de détail, tel ou
tel warning. Alors j'en ai eu marre de taper un retour de malloc() non
casté ou une autre entourloupe pour lever le doute.
Et là, j'ai tout copié collé, le but étant, vous avez dû vous en rendre
compte, de noyer le poisson.
J'ajoute que le plus souvent et sauf raison particulière j'écris mon
code "utile", même "plain C", en C++, et que je sais que c'est mal.

--
Pierre Maurette


Jean-Marc Bourguet

unread,
Nov 29, 2006, 9:30:21 AM11/29/06
to
Pierre Maurette <maurett...@wanadoo.fr> writes:

> Jean-Marc Bourguet, le 29/11/2006 a écrit :
> > Pierre Maurette <maurett...@wanadoo.fr> writes:
> >
> >> #if defined(__cplusplus)
> >> #error C++ compiler not allowed
> >> #endif
> >
> > Quel est l'objectif? Ça n'a un interet que si on a identifie l'utilisation
> > d'une difference de comportement entre le C et le C++ et qu'on l'indique.
> > Sinon, le seul effet est d'em... le pauvre type qui va devoir se tapper
> > l'ecriture d'un script pour pour virer ces lignes-la de tous les fichiers
> > quand il faudra compiler le code avec un compilateur C++. Murphy va
> > naturellement frapper et l'utilisation de ce script va faire manquer le
> > fichier unique ou la precaution etait necessaire et documentee.
>
> Je comprends que vous citiez Murphy, spécialiste de l'emmerdement maximum.
> Vous écrivez un film sur la destination d'un bout de code. Il s'agit d'un
> modèle me servant à faire des tests,

S'assurer que des tests de particularites de C sont bien compilee avec un
compilateur C est une raison parfaitement valable chez moi.

> J'ajoute que le plus souvent et sauf raison particulière j'écris mon code
> "utile", même "plain C", en C++, et que je sais que c'est mal.

Ecrire du code qui reste consciemment dans l'intersection du C et du C++ me
semble etre une contrainte raisonnable.

--
Jean-Marc

Thierry Chappuis

unread,
Nov 29, 2006, 5:57:28 PM11/29/06
to

Jean-Marc Bourguet a écrit :

<NEWBY>
<HS>
Comment je fais si je désire utiliser du code écrit en C dans un
projet C++, et que j'ai pas mal d'appels à malloc (c'est finalement
relativement courant)? Dois-je caster malloc pour être certain que mon
code compile avec un compilateur C++ ou alors forcer la compilation
avec un compilo C avec:

#if defined(__cplusplus)
#error C++ compiler not allowed
#endif

L'article suivant http://www.cpax.org.uk/prg/writings/casting.php
explique qu'il faut éviter de compiler du code C avec un compilateur
C++. Votre commentaire à ce sujet m'intéresse!
</HS>
</NEWBY>

Thierry

Pascal Bourguignon

unread,
Nov 29, 2006, 8:38:28 PM11/29/06
to
"Thierry Chappuis" <thi...@mujigka.ch> writes:

Le plus simple, c'est de compiler avec un compilateur C,
et de mettre dans chaque header C:

#ifdef __cplusplus
extern "C"{
#endif

...

#ifdef __cplusplus
}
#endif


--
__Pascal Bourguignon__ http://www.informatimago.com/
The rule for today:
Touch my tail, I shred your hand.
New rule tomorrow.

Thierry Chappuis

unread,
Nov 30, 2006, 2:00:48 AM11/30/06
to

Pascal Bourguignon a écrit :

Dans ce cas, le code suivant, placé dans le fichier d'implantation .c
ne pose aucun problème, sauf de s'assurer que le fichier en question
sera bien compilé avec un compilateur C.

#if defined(__cplusplus)
#error C++ compiler not allowed
#endif

Donc, je ne comprend pas la remarque de Jean-Marc Bourguet.

Thierry

Pierre Maurette

unread,
Nov 30, 2006, 3:40:19 AM11/30/06
to
Thierry Chappuis, le 29/11/2006 a écrit :
[...]

> Comment je fais si je désire utiliser du code écrit en C dans un
> projet C++, et que j'ai pas mal d'appels à malloc (c'est finalement
> relativement courant)? Dois-je caster malloc pour être certain que mon
> code compile avec un compilateur C++ ou alors forcer la compilation
> avec un compilo C avec:
>
> #if defined(__cplusplus)
> #error C++ compiler not allowed
> #endif

Notez accessoirement que ces trois lignes ne changeront rien si vous
avez effectivement des malloc() non castés ;-)

> L'article suivant http://www.cpax.org.uk/prg/writings/casting.php
> explique qu'il faut éviter de compiler du code C avec un compilateur
> C++. Votre commentaire à ce sujet m'intéresse!

Vous avez des renseignements ici:
<URL:http://jlecomte.ifrance.com/c++/c++-faq-lite/mixing-c-and-cpp-fr.html>

Ensuite, à vous de choisir une stratégie. Sous réserve, puisque je n'ai
pas d'expérience de travail partagé, il me semble qu'un jeu de
fonctions en C (ou autre langage d'ailleurs) validées devra simplement
être lié au projet C++. Ainsi, leur maintenance reste centralisée, et
vous ne gérez pas vos fonctions globales dans le projet C++. C'est ce
qui se passe avec les API Windows.
Ensuite, il y a le copié-collé de code C dans des méthodes C++. Ça
m'arrive assez fréquemment, à partir soit de code personnel, soit de
code glané sur la toile, soit souvent d'exemples (MSDN pour ne pas le
citer). Là, il y a ce que je voudrais faire et ce que malheureusement
ce que je fais trop souvent.
Le code originalement C va compiler en C++, au prix de quelques
précautions comme le cast des malloc(). Mais il va casser certaines
règles de style fortes de C++. Déjà le malloc(), et son cast "à la C"
qui n'arrange rien. Ça va devenir nauséabond si vous free-ez des
pointeurs obtenus par new, ou si vous delete-ez d'autre obtenus par
malloc(). Donc, un peu de refactoring s'impose. A ce moment-là, autant
ne pas caster les malloc() et/ou ne pas faire le #include qui va bien.
Notez que le realloc() ne peut pas se C++-iser de façon triviale.
Sur le malloc() je suis assez strict. En revanche les trucs du MSDN, je
les copie-colle gaillardement. A une époque, je changeais puérilement
les noms, ce qui est extrêmement couillon si on y réfléchit deux
secondes.

--
Pierre Maurette


Thierry Chappuis

unread,
Nov 30, 2006, 4:56:38 AM11/30/06
to

Pierre Maurette a écrit :

> Thierry Chappuis, le 29/11/2006 a écrit :
> [...]
> > Comment je fais si je désire utiliser du code écrit en C dans un
> > projet C++, et que j'ai pas mal d'appels à malloc (c'est finalement
> > relativement courant)? Dois-je caster malloc pour être certain que mon
> > code compile avec un compilateur C++ ou alors forcer la compilation
> > avec un compilo C avec:
> >
> > #if defined(__cplusplus)
> > #error C++ compiler not allowed
> > #endif
>
> Notez accessoirement que ces trois lignes ne changeront rien si vous
> avez effectivement des malloc() non castés ;-)

Si, elles empêchent de compiler avec un compilateur C++. Je fait
essentiellement de la simulation numérique dans un milieu scientifique
(ingénieurie chimique) où je travaille seul sur mes programme. Donc,
moi non plus, je n'ai pas d'expérience du travaille partagé. Ma ligne
de conduite est donc de compiler mes fichier .c avec un compilateur C
(l'utilisation par erreur d'un compilateur C++ génére une erreur, car
définit la macro __cplusplus).

Dans chaque fichier d'entête, je place les lignes:

#ifdef __cplusplus
extern "C" {
#endif

/* Déclaration des points d'entrée */

#ifdef __cplusplus
}
#endif

Si la compilation des fichiers .c et des fichier .cpp est effectuée
avec des compilateurs C et C++ respectivement, je n'ai aucun problème.

Ma question était relative à la remarque de Jean-Marc Bourguet
concernant l'utilsation de #error ... dans les fichiers .c lorsque la
macro __cplusplus est définie. Ceci me laisse penser que dans le monde
professionnel où on travaille en équipe sur des projets beaucoup plus
gros que les miens, il est fréquent de compiler du code C avec un
compilateur C++. Je sais que c'est hors sujet dans le contexte de ce
post, mais je voulais profiter d'un retour d'expérience de Jean-Marc
Bourguet pour en apprendre plus à ce sujet.

> Ensuite, à vous de choisir une stratégie. Sous réserve, puisque je n'ai
> pas d'expérience de travail partagé, il me semble qu'un jeu de
> fonctions en C (ou autre langage d'ailleurs) validées devra simplement
> être lié au projet C++. Ainsi, leur maintenance reste centralisée, et
> vous ne gérez pas vos fonctions globales dans le projet C++. C'est ce
> qui se passe avec les API Windows.

Ca ressemble à ce que je pratique.

> Ensuite, il y a le copié-collé de code C dans des méthodes C++. Ça
> m'arrive assez fréquemment, à partir soit de code personnel, soit de
> code glané sur la toile, soit souvent d'exemples (MSDN pour ne pas le
> citer). Là, il y a ce que je voudrais faire et ce que malheureusement
> ce que je fais trop souvent.
> Le code originalement C va compiler en C++, au prix de quelques
> précautions comme le cast des malloc(). Mais il va casser certaines
> règles de style fortes de C++. Déjà le malloc(), et son cast "à la C"
> qui n'arrange rien. Ça va devenir nauséabond si vous free-ez des
> pointeurs obtenus par new, ou si vous delete-ez d'autre obtenus par
> malloc(). Donc, un peu de refactoring s'impose. A ce moment-là, autant
> ne pas caster les malloc() et/ou ne pas faire le #include qui va bien.
> Notez que le realloc() ne peut pas se C++-iser de façon triviale.
> Sur le malloc() je suis assez strict. En revanche les trucs du MSDN, je
> les copie-colle gaillardement. A une époque, je changeais puérilement
> les noms, ce qui est extrêmement couillon si on y réfléchit deux
> secondes.

Lorsqu'on fait de copie-collé de code C dans du code C++ (c'est
certainement pas recommandable mais je suis conscient qu'on a pas
toujours le choix dans un contexte professionnel), on ne copie pas des
instruction telles que

#if defined(__cplusplus)
#error C++ compiler not allowed
#endif

Merci pour vos retour d'expérience à ce sujet

P.S. Si c'est complètement HS, n'hésitez pas à me dire. Mon but
n'était pas de détourner ce post de son sujet initial.

Meilleures salutations

Thierry

> --
> Pierre Maurette

Pierre Maurette

unread,
Nov 30, 2006, 5:21:09 AM11/30/06
to
Thierry Chappuis, le 30/11/2006 a écrit :
> Pierre Maurette a écrit :
[...]

>>> #if defined(__cplusplus)
>>> #error C++ compiler not allowed
>>> #endif
>>
>> Notez accessoirement que ces trois lignes ne changeront rien si vous
>> avez effectivement des malloc() non castés ;-)
>
> Si, elles empêchent de compiler avec un compilateur C++.

J'avais exceptionnellement placé un rigolard. Bien sûr, il est
préférable de mettre ces trois lignes. Mais s'il y a " effectivement
des malloc() non castés " dans le code, il ne compilera de toutes
façons pas en C++. C'est d'ailleurs l'origine de l'apparition de ce
malloc() non casté dans cette branche du fil. Quand j'ai un doute (sur
la macro __cplusplus ?), et j'en ai encore parfois face à un
comportement inattendu, ce malloc() le lève. Comme le ferait:

void* p = NULL;
int* q = p;

[...]

> P.S. Si c'est complètement HS, n'hésitez pas à me dire. Mon but
> n'était pas de détourner ce post de son sujet initial.

Vous avez vu quel était le sujet initial ? Votre intervention est en
charte, au moins...
Et puis il me semble que le trafic infernal sur fr.comp.lang.c peut
supporter du HS, voire la plaisanterie de mauvais goût.

--
Pierre Maurette


Jean-Marc Bourguet

unread,
Nov 30, 2006, 5:46:52 AM11/30/06
to
Pascal Bourguignon <p...@informatimago.com> writes:

> Le plus simple, c'est de compiler avec un compilateur C,
> et de mettre dans chaque header C:
>
> #ifdef __cplusplus
> extern "C"{
> #endif
>
> ...
>
> #ifdef __cplusplus
> }
> #endif

Ca ne change rien aux regles du C++. Ca change simplement la convention
d'appel utilisee pour les fonctions qui sont definies dans ce bloc.

--
Jean-Marc

Laurent Deniau

unread,
Nov 30, 2006, 6:02:34 AM11/30/06
to

Et aussi la semantique de inline, de const, de struct, etc...

a+, ld.

Thierry Chappuis

unread,
Nov 30, 2006, 6:05:13 AM11/30/06
to

Pierre Maurette a écrit :

> Thierry Chappuis, le 30/11/2006 a écrit :
> > Pierre Maurette a écrit :
> [...]
> >>> #if defined(__cplusplus)
> >>> #error C++ compiler not allowed
> >>> #endif
> >>
> >> Notez accessoirement que ces trois lignes ne changeront rien si vous
> >> avez effectivement des malloc() non castés ;-)
> >
> > Si, elles empêchent de compiler avec un compilateur C++.
>
> J'avais exceptionnellement placé un rigolard. Bien sûr, il est
> préférable de mettre ces trois lignes. Mais s'il y a " effectivement
> des malloc() non castés " dans le code, il ne compilera de toutes
> façons pas en C++. C'est d'ailleurs l'origine de l'apparition de ce
> malloc() non casté dans cette branche du fil. Quand j'ai un doute (sur
> la macro __cplusplus ?), et j'en ai encore parfois face à un
> comportement inattendu, ce malloc() le lève. Comme le ferait:
>
> void* p = NULL;
> int* q = p;

Merci pour votre réponse. Un message de la forme "C++ compiler not
allowed" a toutefois le mérite d'être explicite.

Thierry

Jean-Marc Bourguet

unread,
Nov 30, 2006, 7:51:10 AM11/30/06
to
"Thierry Chappuis" <thi...@mujigka.ch> writes:

> Jean-Marc Bourguet a écrit :
>
> > Pierre Maurette <maurett...@wanadoo.fr> writes:
> >
> > > #if defined(__cplusplus)
> > > #error C++ compiler not allowed
> > > #endif
> >
> > Quel est l'objectif? Ça n'a un interet que si on a identifie
> > l'utilisation d'une difference de comportement entre le C et le C++ et
> > qu'on l'indique. Sinon, le seul effet est d'em... le pauvre type qui
> > va devoir se tapper l'ecriture d'un script pour pour virer ces
> > lignes-la de tous les fichiers quand il faudra compiler le code avec un
> > compilateur C++. Murphy va naturellement frapper et l'utilisation de
> > ce script va faire manquer le fichier unique ou la precaution etait
> > necessaire et documentee.

> Comment je fais si je désire utiliser du code écrit en C dans un projet


> C++, et que j'ai pas mal d'appels à malloc (c'est finalement relativement
> courant)? Dois-je caster malloc pour être certain que mon
> code compile avec un compilateur C++ ou alors forcer la compilation
> avec un compilo C avec:
>
> #if defined(__cplusplus)
> #error C++ compiler not allowed
> #endif

Si tu as des appels a malloc dont tu ne castes pas le resultat, c'est
inutile: la compilation va s'arreter sur les malloc... je ne vais pas
entrer dans le debat de savoir s'il faut ou non caster le resultat de
malloc en C.

> L'article suivant http://www.cpax.org.uk/prg/writings/casting.php
> explique qu'il faut éviter de compiler du code C avec un compilateur
> C++. Votre commentaire à ce sujet m'intéresse!

Je ne suis pas d'accord avec ses commentaires. Qu'on le veuille ou non, le
C et le C++ partagent un sous-ensemble commun important, qui est presque --
mais pas tout a fait -- equivalent a C90. Donc il y a deux choses qui sont
sensees:
- passer du code C en C++ et continuer a le faire evoluer en C++;
- fournir du code compilable a la fois en C et en C++ parce qu'il doit
etre utilise dans des projets C et C++

Une garde du genre de celles ci-dessus va gener l'execution d'une de ces
choses mais ne l'empecher en rien. Elle ne va meme pas provoquer un examen
du code si elle n'est pas accompagnee d'un commentaire specifique au code
protege sur une difference entre le C et le C++, ou si elle est presente
systematiquement dans tous les fichiers et qu'un tel commentaire est
present dans un ou deux de ceux-ci (apres avoir modifie manuellement 3
fichiers, on ecrit un script pour virer les gardes).

Donc je ne vois que deux utilites:

- empecher une compilation accidentelle du C par un compilateur C++ --
et dans ce cas j'aurais tendance a chercher a ameliorer
l'environnement pour eviter le probleme (mais on ne controle pas
toujours l'environnement)

- prevenir la compilation volontaire de code C en C++ parce qu'il
utilise une difference qui n'est pas detectee a la compilation.
J'aurais tendance a ne pas utiliser cette difference dans un premier
temps; mais pour que ce soit alors utile, il faut d'une part indiquer
quelle est cette difference et pourquoi on l'utilise plutot que
d'ecrire un code plus generique, d'autre part qu'un humain passe sur
le code donc que ces gardes ne soient utilisees que dans ce cas la.

A+

--
Jean-Marc

Jean-Marc Bourguet

unread,
Nov 30, 2006, 7:59:38 AM11/30/06
to

Copie et suivi sur fr.comp.lang.c++.

Laurent Deniau <laurent...@cern.ch> writes:

Non justement. extern "C" n'indique pas que ce qui suit est du code C (on
peut y mettre des classes, des namespaces et d'autres choses qui sont
propres au C++; la seule exception a laquelle je pense pour le moment c'est
les templates). S'il y a un inline, c'est la semantique du C++, et pas
celle du C99 qui date d'apres le C++. Tu ne peux pas y faire des
conversions implicites de void* en int*, const suit les regles du C++, ...

A+

--
Jean-Marc

Thierry Chappuis

unread,
Nov 30, 2006, 8:04:57 AM11/30/06
to

Jean-Marc Bourguet a écrit :

Merci beaucoup pour toutes ces précisions détaillées. Meilleures
salutations

Thierry

Jean-Marc Bourguet

unread,
Nov 30, 2006, 8:25:52 AM11/30/06
to
"Thierry Chappuis" <thi...@mujigka.ch> writes:

> Ma question était relative à la remarque de Jean-Marc Bourguet
> concernant l'utilsation de #error ... dans les fichiers .c lorsque la
> macro __cplusplus est définie. Ceci me laisse penser que dans le monde
> professionnel où on travaille en équipe sur des projets beaucoup plus
> gros que les miens, il est fréquent de compiler du code C avec un
> compilateur C++. Je sais que c'est hors sujet dans le contexte de ce
> post, mais je voulais profiter d'un retour d'expérience de Jean-Marc
> Bourguet pour en apprendre plus à ce sujet.

Je travaille sur un projet (genre dizaines de millions de lignes de code
commence il y a 20 ans avec quelques centaines de programmeurs qui ont
travaille et pour certains travaillent encore dessus) commence en C auquel
du C++ a ete ajoute. Il y a quelques annees, une partie du code C (pas
tout, mais c'est la partie sur laquelle je travaille; je n'ai pas
d'estimation de la proportion de ce qui a ete converti) a ete convertie
pour etre compilee en C++ et est compilee en C++ depuis.

J'ai aussi connaissance de librairies qui sont compilees en C ou en C++
suivant le langage dans lequel le projet qui les lie est ecrit. Une
technique pour malloc/free dans ces projets c'est d'utiliser

#define NEW(type) (((type)*)malloc(sizeof(type)))
#define ARRAYNEW(type,sz) (((type)*)malloc((sz)*sizeof(type)))

A+

--
Jean-Marc

Laurent Deniau

unread,
Nov 30, 2006, 9:08:22 AM11/30/06
to

Oui, je me suis mal exprime, ce qui change c'est que justement que le
code C va suivre la semantique du C++ (je m'etais place du point de vue
du PO, c'est a dire un programmeur C qui voit la semantique de son
header changer).

a+, ld.

PS. FU back to f.c.l.c ;-)

Gaël Tessier

unread,
Nov 30, 2006, 9:40:39 AM11/30/06
to
Pierre Maurette wrote:
> unsigned long MoyenneCoins(coin* Debut, size_t nbr)
> {
> size_t indice;
> unsigned long result = 0, dummy;
> bool overflow = false;
> for(indice = 0; !overflow && (indice < nbr); indice++)
> {
> dummy = result;
> result += *((Debut + indice)->ul);
> overflow = (result < dummy);
> }
> overflow = overflow && (result > ULONG_MAX / nbr);
> puts(overflow ? "Overflow" : "OK");
> return overflow ? ULONG_MAX : result / nbr;
> }

Indépendamment du problème déjà évoqué de tabCoin[0] non intialisé, il
me semble que le test "(result > ULONG_MAX / nbr)" n'est pas
approprié. On ne divise jamais result pas nbr, contrairement à ce que
suggère le nom de la fonction.

--
Gaël Tessier
http://www.tessier-net.org

Pierre Maurette

unread,
Nov 30, 2006, 1:49:13 PM11/30/06
to

Oui, il s'agissait de noyer le poisson, et surtout il ne peut pas y
avoir d'overflow sur result dans cette fonction. On pourrait faire:

unsigned long MoyenneCoins(coin* Debut, size_t nbr)
{
size_t indice;

unsigned long result = 0, reste = 0;
for(indice = 0; indice < nbr; indice++)
{
result += *((Debut + indice)->ul) / nbr;
reste += *((Debut + indice)->ul) % nbr;
}
return result + (reste / nbr);
}

Il faudrait borner nbr, ou tester le dépassement sur reste. Peut-être
un truc comme ça:

inline void AddAnItemInMoyenneCoins(unsigned long* presult
, unsigned long* preste
, size_t nbr
, unsigned long valeur)
{
unsigned long dummy = *preste;
*presult += valeur / nbr;
*preste += valeur % nbr;
if(*preste < dummy)
{
AddAnItemInMoyenneCoins(presult, preste, nbr, ULONG_MAX);
}
}

unsigned long MoyenneCoins(coin* Debut, size_t nbr)
{
size_t indice;

unsigned long result = 0, reste = 0;
for(indice = 0; indice < nbr; indice++)
{
AddAnItemInMoyenneCoins(&result, &reste, nbr, *((Debut +
indice)->ul));
}
return result + (reste / nbr);
}

--
Pierre Maurette


0 new messages