Problème avec xCode pour une déclaration de variable

Karamoko - Modifié le 21 sept. 2023 à 03:07
mamiemando Messages postés 33120 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 21 mai 2024 - 25 sept. 2023 à 14:19

Bonjour,

J'ai un macbook pro 14 pouces et je suis sous la dernière version MacOS Ventura. Je veux commencer la programmation. J'ai installé xcode. Je suis un cours sur le langage C sur openclassroom, mais je bloque sur le début, plus précisément sur le chapitre de déclaration de variable.

Comme indiqué sur openclassroom, pour déclarer la variable, il faut faire

int nombredevies;

... ce que je fais et rien s'affiche, ce qui est normal.

Puis le tutoriel indique que je dois déclarer la variable au début de la fonction, donc je dois commencer par la fonction main soit :

main ()

ou

int main(int argc, char *argv[])

Déjà, je bloque sur ça : quand je mets main () il me met un message d'erreur qui dit :

Excepted function body after function declarator

et quand j'écris pour la seconde, il me dit :

redefinition of 'main'. 

Sachant que au tout debut du projet il y'a déjà un programme remplit avec une fonction de manière standard sur xcode je pense.

3 réponses

Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 168
Modifié le 21 sept. 2023 à 03:08

Bonjour,

En gros, ça donnerait ça:

#include <stdio.h>

int main(void) {
    int toto;
    printf("hello\n");
    return 0;
}
0
[Dal] Messages postés 6182 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 22 mai 2024 1 084
18 sept. 2023 à 18:16

Salut Karamoko,

Sachant que au tout debut du projet il y'a déjà un programme remplit avec une fonction de manière standard sur xcode je pense.

Tu dois effacer tout le contenu par défaut présenté de manière standard dans le code source par Xcode avant de taper ton code comme indiqué dans le tutoriel.

0
mamiemando Messages postés 33120 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 21 mai 2024 7 753
21 sept. 2023 à 03:26

Bonjour,

Quelques explications complémentaires :

  • En C, une fonction est implémentée suivant le format suivant :
  • type_de_retour nom_de_la_fonction(
        type_1 parametre_1,
        type_2 parametre_2,
        ...
    ) {
        instruction_1;
        instruction_2;
        ...
    }
  • Voici un exemple :
    int ajouter(int a, int b) {
        return a + b;
    }
  • Si la fonction ne retourne rien, le type de retour est void. Certains compilateur permettent de sous-entendre le type de retour quand il s'agit de void, mais c'est une mauvaise habitude, je te recommande donc de le mettre (cela correspond à ta première erreur). Si la fonction ne prend pas d'argument, on peut mettre void dans la paire de parenthèse qui suit son nom, ou sous-entendre void. Ces deux aspects sont illustrés dans cet exemple :
    #include <stdio.h>
    
    void hello() {
        printf("hello");
    }
  • En C, Une nom de fonction ne peut être utilisé qu'une et une seule fois dans tout ton projet. Le nom de la fonction définit la signature d'une fonction (cela correspond à ta seconde erreur). La notion de signature dépend du langage (par exemple en C++, une fonction est identifiée par son nom et le type de ses paramètres).
  • En C (et en C++), un exécutable doit avoir exactement une fonction main, sans quoi, le compilateur ne sait pas où ton programme démarrer l'exécution.
    • Par convention, la fonction main est sensée retourner un entier (0 si tout va bien, une valeur non nulle en cas d'erreur, supposée être documentée). Cet entier, appelé code d'exécution, est exploité par le système d'exploitation si ton programme s'est correctement exécuté.
  • Au stade où tu en es :
    • un programme est composé d'un ensemble de fonctions
    • toute variable est déclarée dans une fonction.
    • ainsi un programme complet peut ressembler à ceci :
      #include <stdio.h>
      
      void hello() {
          printf("hello");
      }
      
      int ajouter(int a, int b) {
          return a + b;
      }
      
      int main() {
          int x = 7;
          int y = 8;
          int somme;
      
          hello();
          somme = ajouter(x, y);
          printf("somme = %d\n", somme);
          return 0;
      }
    • Comme tu le vois, on a exactement une fonction main ; les fonctions portent toutes des noms différents ; les variables (ici x, y, somme) sont toutes déclarées dans une fonction ; main retourne 0 quand tout va bien (c'est-à -ire tout le temps, dans cet exemple)

Bonne chance

0
[Dal] Messages postés 6182 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 22 mai 2024 1 084
21 sept. 2023 à 16:19

Salut mamiemando,

J'ai une nette préférence, en C, pour mentionner systématiquement et explicitement le type void dans les définitions de fonctions, sachant que le C distingue la signification des parenthèses vides qui signifient, selon le cas :

  • pour une définition de fonction : que celle-ci ne prend aucun paramètre, équivalente à void
  • pour une déclaration de fonction : que celle-ci prend un nombre de paramètres non spécifié

En C++ les parenthèses vides signifient, dans les deux cas, aucun paramètre et sont équivalentes à "void". Ce n'est pas le cas en C.

Voir https://softwareengineering.stackexchange.com/a/287002/321761 (avec les liens vers les standards du C et du C++).

Ton programme n'est pas incorrect, mais il peut induire en erreur un débutant qui peut penser, lorsqu'il devra déclarer un prototype de fonction ne prenant aucun paramètre, qu'il peut le faire avec des parenthèses vides.

Je proposerai, quant à moi :

#include <stdio.h>

void hello(void) {
    printf("hello");
}

int ajouter(int a, int b) {
    return a + b;
}

int main(void) {
    int x = 7;
    int y = 8;
    int somme;

    hello();
    somme = ajouter(x, y);
    printf("somme = %d\n", somme);
    return 0;
}
1
mamiemando Messages postés 33120 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 21 mai 2024 7 753 > [Dal] Messages postés 6182 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 22 mai 2024
Modifié le 21 sept. 2023 à 16:29

Intéressant. J'ai toujours pensé (à tort) que :

void f() {}

... équivalait à :

void f(void) {}

... alors qu'elle correspond (comme tu le soulignes fort justement) à :

void f(...) {}

C'est cette écriture que j'aurais adoptée.

Donc oui, mettre préciser void au niveau des paramètres d'une fonction qui n'en prend pas est clairement plus indiqué. Merci pour ta vigilance.

0
[Dal] Messages postés 6182 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 22 mai 2024 1 084 > mamiemando Messages postés 33120 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 21 mai 2024
Modifié le 22 sept. 2023 à 13:06

Bonjour mamiemando,

Non, ton code était correct comme je l'ai indiqué et :

void f() {}

équivaut bien à :

void f(void) {}

selon le standard, car ici les parenthèses vides sont utilisées dans le contexte d'une définition de fonction (les accolades vont contenir le code de la fonction).

en revanche, si je déclare un prototype de fonction, par exemple dans un fichier d'entête .h :

void f();

en C, les parenthèses vides dans ce contexte signifient que je déclare une fonction dont les paramètres ne sont pas spécifiés, qui peut prendre n'importe quel nombre et type de paramètres.

Avec un compilateur C++, cette subtilité n'existe pas et les parenthèses vides signifient toujours "void". Ce n'est pas le cas en C pour des raisons essentiellement historiques.

Les références aux standards du C et du C++ pertinentes sur ce sujet sont citées dans le post dont j'ai donné le lien sur Stack Exchange.

C'est pourquoi en tant que programmeur C, je préfère toujours indiquer explicitement "void" dans l'un ou l'autre cas.

0
mamiemando Messages postés 33120 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 21 mai 2024 7 753 > [Dal] Messages postés 6182 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 22 mai 2024
22 sept. 2023 à 15:19

J'ai l'impression que ce n'est pas qu'au niveau de la déclaration, et je pense qu'il y a vraiment équivalence entre (...) et () en tout cas avec gcc (Debian 13.2.0-3) 13.2.0.

Ceci compile sans avertissement :

void hello() {}

int main() {
    hello(6, 7);
    return 0;
}
void hello(...) {}

int main() {
    hello(6, 7);
    return 0;
}

... mais pas :

void hello(void) {}

int main() {
    hello(6, 7);
    return 0;
}
0
[Dal] Messages postés 6182 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 22 mai 2024 1 084 > mamiemando Messages postés 33120 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 21 mai 2024
22 sept. 2023 à 17:59

Avec un compilateur C, ton 2ème code ne devrait pas compiler.

L'utilisation de l'ellipse (le ...) qui permet de déclarer des fonctions avec une va_list n'est permise en C que s'il existe au moins un argument spécifié avant les ...

$ gcc -Wall -Wextra 37912410.c
37912410.c:1:12: error: ISO C requires a named argument before ‘...’
 void hello(...) {}
            ^~~

N'est pas plutôt g++ avec lequel tu as testé ce code ?

0