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
Gabriel Dos Reis
-ed- writes:


[...]

| > si c'est une fonction qui le manipule comme handle opaque, et qui se co ntente
| > de le passer a une autre fonction, c'est tres cretin.
|
| Techniquement il est très rare que FILE soit un véritable type opaque,
| car pour implémenter les macros getc()et putc(), on a besoin des
| éléments de la structure...

Non, pas forcément.
C'est parfaitement légal de les définir commes des macros qui d élèguent
le vrai boulot à des fonctions internes.

-- Gaby
Avatar
espie
In article ,
-ed- wrote:
On 14 sep, 20:01, (Marc Espie) wrote:
>En quel sens FILE est une connerie ?

Par exemple, ca te rend impossible de prototyper une fonction qui prend
un fichier ouvert en parametre sans inclure stdio.h...



Ce qui me parait être de bon sens. Comment utiliser un type qui
n'aurait pas été défini ?

si c'est une fonction qui le manipule comme handle opaque, et qui se contente
de le passer a une autre fonction, c'est tres cretin.



Techniquement il est très rare que FILE soit un véritable type opaque,
car pour implémenter les macros getc()et putc(), on a besoin des
éléments de la structure...



Je ne vois pas trop comment FILE peut etre autre chose qu'une structure
(surtout vu que c'est FILE * qu'on utilise).

Partant de la, je ne vois pas trop l'interet a ne pas avoir un
struct file * a la place...
Avatar
Marc
Gabriel Dos Reis wrote:

| Techniquement il est très rare que FILE soit un véritable type opaque,
| car pour implémenter les macros getc()et putc(), on a besoin des
| éléments de la structure...



Je ne crois pas que getc et putc soient forcément des macros, c'est juste
une possibilité.

Non, pas forcément.
C'est parfaitement légal de les définir commes des macros qui délèguent
le vrai boulot à des fonctions internes.



Et c'est même une très bonne idée de cacher tout ce qui touche à FILE, si
on veut avoir une chance de faire évoluer l'implémentation sans
abandonner la compatibilité binaire.
Avatar
Gabriel Dos Reis
(Marc Espie) writes:

| In article ,
| -ed- wrote:
| >On 14 sep, 20:01, (Marc Espie) wrote:
| >> >En quel sens FILE est une connerie ?
| >>
| >> Par exemple, ca te rend impossible de prototyper une fonction qui prend
| >> un fichier ouvert en parametre sans inclure stdio.h...
| >
| >Ce qui me parait être de bon sens. Comment utiliser un type qui
| >n'aurait pas été défini ?
| >
| >> si c'est une fonction qui le manipule comme handle opaque, et qui se contente
| >> de le passer a une autre fonction, c'est tres cretin.
| >
| >Techniquement il est très rare que FILE soit un véritable type opaque,
| >car pour implémenter les macros getc()et putc(), on a besoin des
| >éléments de la structure...
|
| Je ne vois pas trop comment FILE peut etre autre chose qu'une structure
| (surtout vu que c'est FILE * qu'on utilise).

Et pourtant open() de POSIX n'a pas de mal à retourner un entier comme
abstraction pour l'entité de fichier derrière.

-- Gaby
Avatar
espie
In article ,
Gabriel Dos Reis wrote:
(Marc Espie) writes:

| In article
,
| -ed- wrote:
| >On 14 sep, 20:01, (Marc Espie) wrote:
| >> >En quel sens FILE est une connerie ?
| >>
| >> Par exemple, ca te rend impossible de prototyper une fonction qui prend
| >> un fichier ouvert en parametre sans inclure stdio.h...
| >
| >Ce qui me parait être de bon sens. Comment utiliser un type qui
| >n'aurait pas été défini ?
| >
| >> si c'est une fonction qui le manipule comme handle opaque, et qui
se contente
| >> de le passer a une autre fonction, c'est tres cretin.
| >
| >Techniquement il est très rare que FILE soit un véritable type opaque,
| >car pour implémenter les macros getc()et putc(), on a besoin des
| >éléments de la structure...
|
| Je ne vois pas trop comment FILE peut etre autre chose qu'une structure
| (surtout vu que c'est FILE * qu'on utilise).

Et pourtant open() de POSIX n'a pas de mal à retourner un entier comme
abstraction pour l'entité de fichier derrière.



open retourne un int, pas un int *. La nuance est quand meme de taille.
Et il ne se cache "rien" derriere, en particulier pas de tampon manipulable
au niveau utilisateur (dis, tu vas quand meme pas essayer de m'apprendre l'API
Unix ?)
Avatar
Gabriel Dos Reis
(Marc Espie) writes:

| In article ,
| Gabriel Dos Reis wrote:
| > (Marc Espie) writes:
| >
| >| In article
| >,
| >| -ed- wrote:
| >| >On 14 sep, 20:01, (Marc Espie) wrote:
| >| >> >En quel sens FILE est une connerie ?
| >| >>
| >| >> Par exemple, ca te rend impossible de prototyper une fonction qui prend
| >| >> un fichier ouvert en parametre sans inclure stdio.h...
| >| >
| >| >Ce qui me parait être de bon sens. Comment utiliser un type qui
| >| >n'aurait pas été défini ?
| >| >
| >| >> si c'est une fonction qui le manipule comme handle opaque, et qui
| >se contente
| >| >> de le passer a une autre fonction, c'est tres cretin.
| >| >
| >| >Techniquement il est très rare que FILE soit un véritable type opaque,
| >| >car pour implémenter les macros getc()et putc(), on a besoin des
| >| >éléments de la structure...
| >|
| >| Je ne vois pas trop comment FILE peut etre autre chose qu'une structure
| >| (surtout vu que c'est FILE * qu'on utilise).
| >
| >Et pourtant open() de POSIX n'a pas de mal à retourner un entier comme
| >abstraction pour l'entité de fichier derrière.
|
| open retourne un int, pas un int *.

Je crois que j'ai bien dit entier et pas autre chose.

| La nuance est quand meme de taille.

C'est exact. Mais, je ne vois personne prétendre que open() retourne un
« int * » Donc, effectivement la différence est de taille, mais elle
n'a aucune espèce d'importance ici.

| Et il ne se cache "rien" derriere, en particulier pas de tampon manipulable
| au niveau utilisateur

Quelque chose se cache derrière ce « int ». Tu ne peux pas te fabriquer
n'importe quel entier comme cela et le passer comme premier paramètre à
read() et espérer que quelque chose de merveilleux va se réaliser.

| (dis, tu vas quand meme pas essayer de m'apprendre l'API Unix ?)

Non, juste la notion d'abstraction :-p

-- Gaby
Avatar
bpascal123
Bsr/jr,

Je commence avec les pointeurs et je voudrais comprendre le code de ce
tutorial :
http://www.ltam.lu/Tutoriel_Ansi_C/

Je ne sais pas comment l'auteur à organiser ces liens html mais je ne
peux pas copier-coller le lien exact de la page ou se trouve le
code...pour faire bref, il s'agit de l'exercice 9.5 dans le chapitre
des pointeurs.

Il y a diverses questions dans à l'intérieur du code ci-dessous :

#include <stdio.h>

int main(void)
{
int TabA[] = { 31, 62, 17, 28, 45, 62, 34, 22, 62 } ;
int *p1 = TabA ;
int *p2 = TabA ;
int n ;
int nbr ;

printf("nnEcrire un programme qui lit un entier nbr et un rayon
d'entiers TabA n"
"du type int au clavier et élimine toutes les occurrences de nbr dans
TabA n"
"en tassant les éléments restants. Le programme utilisera n"
"les pointeurs p1 et p2 pour parcourir le rayon.n") ;

n = sizeof(TabA) / sizeof(int) ;

/* code intermédiaire pour comprendre le déroulement du prg */
printf("nnnUST FOR INFO 1 n(juste apres l'affectation et
l'initialisation des valeurs et variables) : n" ) ;
printf("---------------------------------------------------------
n") ;
printf("nTaille de int : %dn", sizeof(int)) ;
printf("nnn = %dtp1 = %dtp2 = %dtTabA = %dn", n, p1, p2,
TabA) ;

/* Reprise du programme */

printf("nn") ;

printf("Affichage du rayon de valeurs int non modifie : nn") ;

for ( p1 ; p1 < TabA+n ; p1++ )
printf("%dt", *p1) ;

/* code intermédiaire pour comprendre le déroulement du prg */
printf("nnJUST FOR INFO 2 n(apres l'affichage des valeurs avec le
pointeur p1) : n" ) ;
printf("---------------------------------------------------------
n") ;
printf("nnn = %dtp1 = %dtp2 = %dtTabA = %dn", n, p1, p2,
TabA) ;

/* Reprise du programme */

printf("nnEntrez un entier a supprimer : n") ;
nbr = 62 ;
printf("...n") ;
printf("Le nombre est : %d nn", nbr) ;

for ( p1 = TabA ; p1 < TabA+n ; p1++ )
{
*p2 = *p1 ;
if ( *p2 != nbr )
p2++ ;
}

/* code intermédiaire pour comprendre le déroulement du prg */
printf("nnJUST FOR INFO 3 n(apres la recherche de la valeur a
supprimer avec les pointeur p1 et p2) : n"
"et apres l'affectation du tableau sans la valeur dans p2.n") ;
printf("---------------------------------------------------------
n") ;
printf("nnn = %dtp1 = %dtp2 = %dtTabA = %dn", n, p1, p2,
TabA) ;




/***************************************************

Question 1:

A ce niveau, si je boucle avec p2, les valeurs renvoyees sont :
("n" n'a pas été redimensionné)

{ 31, 17, 28, 45, 34, 22, 62, 22, 62 }

printf("np2: n" ) ;
for ( p2 = TabA ; p2 < TabA+n ; p2 ++ )
printf("%dt", *p2 ) ;

Les valeurs renvoyees sont toujours au nombre de 10 comme lors de
leur initialisation
mais a partir de l'indice 6 soit 22, je ne comprends pas les valeurs
que je retrouve
après cet indice soit 62, 22, 62.

***************************************************/

/* Reprise du programme */

n = p2 - TabA ;

printf("nnAffichage du nouveau rayon de valeurs int : nn") ;

for ( p2 = TabA ; p2 < TabA+n ; p2++ )
printf("%dt", *p2) ;

/* code intermédiaire pour comprendre le déroulement du prg */
printf("nnJUST FOR INFO 5 n(apres l'affichage du resultat avec
p2) : n"
""n" a ete redimensionne et p2 remis au debut du rayonn") ;
printf("---------------------------------------------------------
n") ;
printf("nnn = %dtp1 = %dtp2 = %dtTabA = %dn", n, p1, p2,
TabA) ;

/* Reprise du programme */

printf("nn") ;

return 0 ;
}


/* Questions 2:

printf("nTaille de P1 divise par int : %dn", sizeof(p1)/4) ;

- Pourquoi sizeof(p1) renvoie 1 ?

--- alors que sizeof(TabA)/4), renvoie 9 ?

--- en fait sizeof ne fonctionne pas avec les pointeurs ???
--- seulement il y a un débat entre ceux qui disent que les tableaux
sont des pointeurs et ceux qui ne sont pas d'accord avec ça et
qui manquent d'arguments.


/* Questions 3:

Je ne comprends pas comment TabA qui a une valeur de renvoie avec
sizeof identique
tout au long du programme (normal ce n'est pas un pointeur :) ) et n
qui dans sa valeur
initiale est 9 et sa valeur volontairement modifiée renvoyée par n =
p2 - TabA : 6 ...
ALORS QUE p2 sur ma machine a une valeur identique a TabA (chez moi
591036) au debut du déroulement
du programme mais qui est modifiée à partir de "Juste pour info 3" et
qui donne (chez moi) : 591060 alors
la question est comment est ce que dans les boucles correspondantes
591060 < 591036 + 6 ???

Au tout début du programme : le second argument de la boucle est p1 <
TabA + n soit
sur mon système : 591036 < 591036 + 9 .
Là, je trouve que c'est cohérent mais avec p2, j'ai du mal à
comprendre.

Je dois aussi avouer que ces nombre 591036, 591060 ne me parlent pas
beaucoup. Je crois il s'agit de l'affichage
avec une valeur entier d'une adresse dans le buffer. C'est unique à un
instant t a ce qui est dans la mémoire du système.
Par curiosité, s'agit-il de heap ou ou stack ?

*/
Avatar
bpascal123
On 16 sep, 00:52, ""
wrote:
Bsr/jr,

Je commence avec les pointeurs et je voudrais comprendre le code de ce
tutorial :http://www.ltam.lu/Tutoriel_Ansi_C/

Je ne sais pas comment l'auteur à organiser ces liens html mais je ne
peux pas copier-coller le lien exact de la page ou se trouve le
code...pour faire bref, il s'agit de l'exercice 9.5 dans le chapitre
des pointeurs.

Il y a diverses questions dans à l'intérieur du code ci-dessous :




Le code sous forme de fichier ou page html moins condensé (plus
lisible) :

http://site.voila.fr/pascal322
Avatar
espie
In article ,
Gabriel Dos Reis wrote:
(Marc Espie) writes:

| In article ,
| Gabriel Dos Reis wrote:
| > (Marc Espie) writes:
| >
| >| In article
| >,
| >| -ed- wrote:
| >| >On 14 sep, 20:01, (Marc Espie) wrote:
| >| >> >En quel sens FILE est une connerie ?
| >| >>
| >| >> Par exemple, ca te rend impossible de prototyper une fonction qui prend
| >| >> un fichier ouvert en parametre sans inclure stdio.h...
| >| >
| >| >Ce qui me parait être de bon sens. Comment utiliser un type qui
| >| >n'aurait pas été défini ?
| >| >
| >| >> si c'est une fonction qui le manipule comme handle opaque, et qui
| >se contente
| >| >> de le passer a une autre fonction, c'est tres cretin.
| >| >
| >| >Techniquement il est très rare que FILE soit un véritable type opaque,
| >| >car pour implémenter les macros getc()et putc(), on a besoin des
| >| >éléments de la structure...
| >|
| >| Je ne vois pas trop comment FILE peut etre autre chose qu'une structure
| >| (surtout vu que c'est FILE * qu'on utilise).
| >
| >Et pourtant open() de POSIX n'a pas de mal à retourner un entier comme
| >abstraction pour l'entité de fichier derrière.
|
| open retourne un int, pas un int *.

Je crois que j'ai bien dit entier et pas autre chose.

| La nuance est quand meme de taille.

C'est exact. Mais, je ne vois personne prétendre que open() retourne un
« int * » Donc, effectivement la différence est de taille, mais elle
n'a aucune espèce d'importance ici.

| Et il ne se cache "rien" derriere, en particulier pas de tampon manipulable
| au niveau utilisateur

Quelque chose se cache derrière ce « int ». Tu ne peux pas te fabriquer
n'importe quel entier comme cela et le passer comme premier paramètre à
read() et espérer que quelque chose de merveilleux va se réaliser.

| (dis, tu vas quand meme pas essayer de m'apprendre l'API Unix ?)

Non, juste la notion d'abstraction :-p



Ben commence par l'apprendre au comite de normalisation (enfin, c'est 30
ans trop tard, vu les usages): FILE * est le cul entre deux chaises, d'autant
plus que tu n'as pas le droit d'utiliser directement FILE (ce qui n'empeche
pas certains d'essayer, ce qui nous a donne des problemes scabreux quand on
a change la taille de la structure dans la libc). Je trouve ca debile de
faire "une moitie" d'abstraction, soit on y va carrement, mais laisser
des trucs a la n'importe quoi, genre FILE *, ca cause plus d'emmerdes
qu'autre chose.

- c'est pas plus intelligent de savoir que FILE * est un pointeur que de
se dire que FILE est une structure.
- en plus, comme c'est un pointeur, ca empeche que ca soit un entier. C'est
balot: ca faisait une implementation triviale a peu pres conforme de stdio
au-dessus de posix.

Bref, c'est une demie-abstraction pourrie. Je ne vois aucun interet a
definir FILE si c'est pour bastardiser la chose en FILE * derriere. Et je n'y
vois que des inconvenients, plus ou moins futiles selon le point de vue.
Avatar
Gabriel Dos Reis
(Marc Espie) writes:

| In article ,
| Gabriel Dos Reis wrote:
| > (Marc Espie) writes:
| >
| >| In article ,
| >| Gabriel Dos Reis wrote:
| >| > (Marc Espie) writes:
| >| >
| >| >| In article
| >| >,
| >| >| -ed- wrote:
| >| >| >On 14 sep, 20:01, (Marc Espie) wrote:
| >| >| >> >En quel sens FILE est une connerie ?
| >| >| >>
| >| >| >> Par exemple, ca te rend impossible de prototyper une fonction qui prend
| >| >| >> un fichier ouvert en parametre sans inclure stdio.h...
| >| >| >
| >| >| >Ce qui me parait être de bon sens. Comment utiliser un type qui
| >| >| >n'aurait pas été défini ?
| >| >| >
| >| >| >> si c'est une fonction qui le manipule comme handle opaque, et qui
| >| >se contente
| >| >| >> de le passer a une autre fonction, c'est tres cretin.
| >| >| >
| >| >| >Techniquement il est très rare que FILE soit un véritable type opaque,
| >| >| >car pour implémenter les macros getc()et putc(), on a besoin des
| >| >| >éléments de la structure...
| >| >|
| >| >| Je ne vois pas trop comment FILE peut etre autre chose qu'une structure
| >| >| (surtout vu que c'est FILE * qu'on utilise).
| >| >
| >| >Et pourtant open() de POSIX n'a pas de mal à retourner un entier comme
| >| >abstraction pour l'entité de fichier derrière.
| >|
| >| open retourne un int, pas un int *.
| >
| >Je crois que j'ai bien dit entier et pas autre chose.
| >
| >| La nuance est quand meme de taille.
| >
| >C'est exact. Mais, je ne vois personne prétendre que open() retourne un
| >« int * » Donc, effectivement la différence est de taille, mais elle
| >n'a aucune espèce d'importance ici.
| >
| >| Et il ne se cache "rien" derriere, en particulier pas de tampon manipulable
| >| au niveau utilisateur
| >
| >Quelque chose se cache derrière ce « int ». Tu ne peux pas te fabriquer
| >n'importe quel entier comme cela et le passer comme premier paramètre à
| >read() et espérer que quelque chose de merveilleux va se réaliser.
| >
| >| (dis, tu vas quand meme pas essayer de m'apprendre l'API Unix ?)
| >
| >Non, juste la notion d'abstraction :-p
|
| Ben commence par l'apprendre au comite de normalisation (enfin, c'est 30
| ans trop tard, vu les usages): FILE * est le cul entre deux chaises, d'autant
| plus que tu n'as pas le droit d'utiliser directement FILE (ce qui n'empeche
| pas certains d'essayer, ce qui nous a donne des problemes scabreux quand on
| a change la taille de la structure dans la libc). Je trouve ca debile de
| faire "une moitie" d'abstraction, soit on y va carrement, mais laisser
| des trucs a la n'importe quoi, genre FILE *, ca cause plus d'emmerdes
| qu'autre chose.

Pourquoi penses-tu que c'est la moitié d'une abstraction ?

| - c'est pas plus intelligent de savoir que FILE * est un pointeur que de
| se dire que FILE est une structure.

C'est vrai. Mais cela aucune espèce d'importance pratique. Comme c'est
une abstraction, la seule la manière de s'en servir correctement, c'est
à travers l'interface.

| - en plus, comme c'est un pointeur, ca empeche que ca soit un entier.

Pas forcément. Et de toute façon, cela n'a aucune espèce d'importance
que ce soit un pointeur ou un entier.

| C'est balot: ca faisait une implementation triviale a peu pres
| conforme de stdio au-dessus de posix.

la bibliothèque standard fait partie de l'implémentation. Ce qui est
« trivial » dépend fortement des caractéristique profondes de
l'implémentation.

| Bref, c'est une demie-abstraction pourrie. Je ne vois aucun interet a
| definir FILE si c'est pour bastardiser la chose en FILE * derriere.

Cela n'est pas évident que c'est une demi-abstraction ou que c'est
pourri comme abstraction. Tu peux souhaiter d'autres choix pour
d'autres raisons que tu n'as pas encore exposées, mais jusqu'à présent
je ne trouve rien de convainquant dans ton « accusation ».

| Et je n'y vois que des inconvenients, plus ou moins futiles selon le
| point de vue.


-- Gaby