OVH Cloud OVH Cloud

Différence de résultat entre compilateurs

291 réponses
Avatar
YannicK
Bonjour,

éternel débutant en C pour mon plaisir, je me permets de venir vous
demander quelques éclaircissements sur une situation que je n'arrive pas
à comprendre :

J'utilise le cours en ligne spécial "grand débutant" du "site du zéro" :
<http://www.siteduzero.com/tutoriel-3-14189-apprenez-a-programmer-en-c.html>

Je réalise les exercices du cours dans deux environnements différents :
- sous windows vista avec l'IDE visual C++ 2008 express
- sous linux ubuntu 9.04 avec gcc

J'ai écrit un programme dans le cadre des exercices proposés sur les
tableaux par ce cours en ligne. Le fichier en question peut être
téléchargé ici :
< http://dl.free.fr/to7PFReLM/tableau.c>

Ce qui m'étonne, c'est que j'arrive à compiler sans difficulté ce code
sous Linux, et que le programme se comporte exactement comme je le
souhaite. Par contre, sous Windows, impossible de compiler, l'IDE me
renvoie 42 erreurs et 31 avertissements !!! La plupart des erreurs
semblent être liées aux variables. Par exemple :
"erreur de syntaxe : absence de ';' avant 'type'"
"identificateur non déclaré"

Or, j'ai beau lire et relire mon code, les variables me sembles toutes
déclarées correctement et il ne manque à mon sens pas de ";" en fin
d'instructions. De plus, comme je le disais au début, le même code se
compile sans aucune erreur sous Linux ...

Alors, comment expliquer que deux compilateurs réagissent aussi
différemment, et où et mon erreur ?

Merci par avance du temps que vous pourrez me consacrer,



--
YannicK
yann801 *arobase* yahoo *point* fr
yann801 *at* yahoo *dot* fr

10 réponses

Avatar
Manuel Pégourié-Gonnard
candide scripsit:

Mais la question n'est pas là, le pointeur est transparent pour
l'utilisateur, c'est tout ce qui compte.



Je ne trouve pas qu'il soit transparent, et tu expliques toi-même
pourquoi ci-dessous.

Il suffit jusque que
l'utilisateur sache qu'il peut modifier le contenu du tableau passé en
paramètre depuis sa fonction, le pourquoi du comment, on s'en fout,
dans un premier temps du moins.



Donc c'est pas transparent. Ça crée une règle en apparence arbiraire du
genre « on peut pas modifier les paramètres depuis une fonction, sauf si
c'est des tableaux ». Si l'utilisateur me ressemble un tant soit peu, au
bout de quelques règles arbitraires comme ça, il décrète que le truc (le
langage ou le cours, au choix) est un m*rdier incohérent et il décroche.

Il me semblait que t'avais compris la
différence qu'il peut y avoir entre une interface et une
implémentation, les cordonniers ....



Mauvais exemple. Là, ce qui guide le comportement de l'interface (« on
peut modifier les arguments si c'est des tableaux ») est justement
l'implémentation. Donc il y a de toutes façon un couplage fort entre les
deux dans ce cas précis, contrairement aux grands principes qu'on nous
apprend en général. C'est pas forcément une bonne idée au niveau
pédagogique que de vouloir nier cette réalité.

--
Manuel Pégourié-Gonnard Institut de mathématiques de Jussieu
http://weblog.elzevir.fr/ http://people.math.jussieu.fr/~mpg/
Avatar
Manuel Pégourié-Gonnard
Marc Espie scripsit:

In article <4aae3487$0$7785$,
Stephane Legras-Decussy wrote:

plus simplement j'ai constaté que le débutant
est completement perdu à cause de '*'
qui dans un cas déclare le pointeur int *p
et dans l'autre cas est un opérateur a = *p





J'avoue que c'est un truc qui m'a chiffoné un bon moment.

Bof, ca c'est pas un vrai souci, de mon point de vue. Ca depend comment
tu expliques. Pour moi, int *p, ca te dit que l'expression *p est de
type int. Et donc c'est le meme operateur.



Hum. Il me semble qu'il y a quand même une grande différence entre

int a;
int *p;

car dans le premier cas 'a' est effectivement un objet de type int que
tu peux utiliser directement, alors que dans le deuxième cas, tu dois te
farcir l'allocation de mémoire avant de pouvoir considérer que
l'expression *p est un truc de type int valide.

Bref, j'ai peut-être tort, mais dans ma tête je préfère me dire qu'il y
a effectivement deux opérateurs '*' différents, l'un qui sert à
déréférencer et l'autre à construire des types, et que c'est raisonnable
de les nommer pareil à cause de l'argument que tu donnes.

--
Manuel Pégourié-Gonnard Institut de mathématiques de Jussieu
http://weblog.elzevir.fr/ http://people.math.jussieu.fr/~mpg/
Avatar
Pierre Maurette
Manuel Pégourié-Gonnard, le 14/09/2009 a écrit :
Marc Espie scripsit:

In article <4aae3487$0$7785$,
Stephane Legras-Decussy wrote:

plus simplement j'ai constaté que le débutant
est completement perdu à cause de '*'
qui dans un cas déclare le pointeur int *p
et dans l'autre cas est un opérateur a = *p





J'avoue que c'est un truc qui m'a chiffoné un bon moment.

Bof, ca c'est pas un vrai souci, de mon point de vue. Ca depend comment
tu expliques. Pour moi, int *p, ca te dit que l'expression *p est de
type int. Et donc c'est le meme operateur.



Hum. Il me semble qu'il y a quand même une grande différence entre

int a;
int *p;

car dans le premier cas 'a' est effectivement un objet de type int que
tu peux utiliser directement, alors que dans le deuxième cas, tu dois te
farcir l'allocation de mémoire avant de pouvoir considérer que
l'expression *p est un truc de type int valide.

Bref, j'ai peut-être tort, mais dans ma tête je préfère me dire qu'il y
a effectivement deux opérateurs '*' différents, l'un qui sert à
déréférencer et l'autre à construire des types, et que c'est raisonnable
de les nommer pareil à cause de l'argument que tu donnes.



Je me répète, mais je trouve que:

int a;
int* p;

est bien plus clair. En fait impérativement:

int a;
int* p = NULL;/* ou int* p = &a; ou int* p = malloc(sizeof *p); */

--
Pierre Maurette
Avatar
Richard Delorme
Le 14/09/2009 18:42, Pierre Maurette a écrit :

Je me répète, mais je trouve que:

int a;
int* p;

est bien plus clair.



Moi je ne trouve pas.

Entre autre parce que :

int* p, a;

ne déclare pas deux pointeurs.

--
Richard
Avatar
Manuel Pégourié-Gonnard
candide scripsit:

Ce n'est pas mon avis. Bien sûr si tu parles abstraitement pour
décrire des choses abstraites... Je ne crois pas vraiemnt à cette
histoire de "faculté d'abstraction" comme si ça existait
intrinsèquement.



Moi si, alors essayons de préciser. Ce que tu expliques, c'est que tout
n'est pas tout blanc ou tout noir, que (presque) tout le monde est
capable de comprendre des concepts qui sont un peu abstraits. Jusque-là
on est d'accord mais le constat est un peu banal.

Ce qui est important, c'est la capacité, quand on est confronté à une
abstraction /nouvelle/, d'arriver rapidement à la considérer comme
quelque chose de naturel, qu'on peut manipuler facilement, et sur quoi
on peut alors s'appuyer pour comprendre d'autres choses.

Et cette capacité-là, l'expérience (en tout cas la mienne) montre
qu'elle est très variable selon les individus et leur parcours.

--
Manuel Pégourié-Gonnard Institut de mathématiques de Jussieu
http://weblog.elzevir.fr/ http://people.math.jussieu.fr/~mpg/
Avatar
Pierre Maurette
Richard Delorme, le 14/09/2009 a écrit :
Le 14/09/2009 18:42, Pierre Maurette a écrit :

Je me répète, mais je trouve que:

int a;
int* p;

est bien plus clair.



Moi je ne trouve pas.

Entre autre parce que :

int* p, a;

ne déclare pas deux pointeurs.



Oui. Je l'ai déjà noté un "peu plus bas". Règle de style, typedef, etc.
Vous ne trouvez pas ça /bien plus clair/ parce que vous le savez, parce
que vous êtes expert. Je me situe - et pourtant je ne suis pas
enseignant, Dieu m'en préserve - par rapport au débutant. Je dirais "s
est un /char étoile/", /char étoile/ est clairement un type (dérivé).

--
Pierre Maurette
Avatar
Gabriel Dos Reis
Manuel Pégourié-Gonnard <mpg+ writes:

| Marc Espie scripsit:
|
| > In article <4aae3487$0$7785$,
| > Stephane Legras-Decussy wrote:
| >>
| >>plus simplement j'ai constaté que le débutant
| >>est completement perdu à cause de '*'
| >>qui dans un cas déclare le pointeur int *p
| >>et dans l'autre cas est un opérateur a = *p
| >
| J'avoue que c'est un truc qui m'a chiffoné un bon moment.
|
| > Bof, ca c'est pas un vrai souci, de mon point de vue. Ca depend comment
| > tu expliques. Pour moi, int *p, ca te dit que l'expression *p est de
| > type int. Et donc c'est le meme operateur.
|
| Hum. Il me semble qu'il y a quand même une grande différence en tre
|
| int a;
| int *p;
|
| car dans le premier cas 'a' est effectivement un objet de type int que
| tu peux utiliser directement, alors que dans le deuxième cas, tu doi s te
| farcir l'allocation de mémoire avant de pouvoir considérer que
| l'expression *p est un truc de type int valide.

Dans le premier cas ("int a;") tu dois affecter une valeur à "a"
avant de pouvoir l'utiliser. Dans le second cas ("int *p;"), tu dois
affecter une valeur à "p" avant de pouvoir l'utiliser. Cette
affectation peut invoquer une allocation de mémoire ou non.
Dans les deux cas, tu dois affecter une valeur à la variable avant de
pouvoir l'utiliser.

-- Gaby
Avatar
Gabriel Dos Reis
Richard Delorme writes:

| Le 14/09/2009 18:42, Pierre Maurette a écrit :
| >
| > Je me répète, mais je trouve que:
| >
| > int a;
| > int* p;
| >
| > est bien plus clair.

C'est ce que j'enseigne à mes élèves.

| Moi je ne trouve pas.
|
| Entre autre parce que :
|
| int* p, a;
|
| ne déclare pas deux pointeurs.

J'ai peu de temps à passer pour expliquer ces subtilités.
Je leur demande une déclaration à la fois -- en général , le code est
beaucoup plus clair ; je trouve.

-- Gaby
Avatar
Pierre Maurette
Gabriel Dos Reis, le 14/09/2009 a écrit :
Manuel Pégourié-Gonnard <mpg+ writes:

Marc Espie scripsit:

In article <4aae3487$0$7785$,
Stephane Legras-Decussy wrote:

plus simplement j'ai constaté que le débutant
est completement perdu à cause de '*'
qui dans un cas déclare le pointeur int *p
et dans l'autre cas est un opérateur a = *p





J'avoue que c'est un truc qui m'a chiffoné un bon moment.

Bof, ca c'est pas un vrai souci, de mon point de vue. Ca depend comment
tu expliques. Pour moi, int *p, ca te dit que l'expression *p est de
type int. Et donc c'est le meme operateur.



Hum. Il me semble qu'il y a quand même une grande différence entre

int a;
int *p;

car dans le premier cas 'a' est effectivement un objet de type int que
tu peux utiliser directement, alors que dans le deuxième cas, tu dois te
farcir l'allocation de mémoire avant de pouvoir considérer que
l'expression *p est un truc de type int valide.



Dans le premier cas ("int a;") tu dois affecter une valeur à "a"
avant de pouvoir l'utiliser. Dans le second cas ("int *p;"), tu dois
affecter une valeur à "p" avant de pouvoir l'utiliser. Cette
affectation peut invoquer une allocation de mémoire ou non.
Dans les deux cas, tu dois affecter une valeur à la variable avant de
pouvoir l'utiliser.



int a;
int* p = NULL;
/* du code */
p = &a;

Je n'ai pas affecté de valeur à a avant de l'utiliser.

--
Pierre Maurette
Avatar
Gabriel Dos Reis
Pierre Maurette writes:

| Gabriel Dos Reis, le 14/09/2009 a écrit :
| > Manuel Pégourié-Gonnard <mpg+ writes:
| >
| >> Marc Espie scripsit:
| >>
| >>> In article <4aae3487$0$7785$,
| >>> Stephane Legras-Decussy wrote:
| >>>>
| >>>> plus simplement j'ai constaté que le débutant
| >>>> est completement perdu à cause de '*'
| >>>> qui dans un cas déclare le pointeur int *p
| >>>> et dans l'autre cas est un opérateur a = *p
| >>>
| >> J'avoue que c'est un truc qui m'a chiffoné un bon moment.
| >>
| >>> Bof, ca c'est pas un vrai souci, de mon point de vue. Ca depend comme nt
| >>> tu expliques. Pour moi, int *p, ca te dit que l'expression *p est de
| >>> type int. Et donc c'est le meme operateur.
| >>
| >> Hum. Il me semble qu'il y a quand même une grande différence entre
| >>
| >> int a;
| >> int *p;
| >>
| >> car dans le premier cas 'a' est effectivement un objet de type int que
| >> tu peux utiliser directement, alors que dans le deuxième cas, tu dois te
| >> farcir l'allocation de mémoire avant de pouvoir considérer q ue
| >> l'expression *p est un truc de type int valide.
| >
| > Dans le premier cas ("int a;") tu dois affecter une valeur à "a"
| > avant de pouvoir l'utiliser. Dans le second cas ("int *p;"), tu dois
| > affecter une valeur à "p" avant de pouvoir l'utiliser. Cette
| > affectation peut invoquer une allocation de mémoire ou non.
| > Dans les deux cas, tu dois affecter une valeur à la variable avant de
| > pouvoir l'utiliser.
|
| int a;
| int* p = NULL;
| /* du code */
| p = &a;
|
| Je n'ai pas affecté de valeur à a avant de l'utiliser.

Nous devons avoir des notions différentes de « utiliser ». La mienne est
beaucoup plus prosaïque, proche du programmeur débutant qui se po se la
question à laquelle je répondait -- en Standardais « &a  » ne demande pas
une conversion de « lvalue » en « non-lvalue. »

-- Gaby