Partage
  • Partager sur Facebook
  • Partager sur Twitter

Différence entre C, C# et C++ ?

C'est quoi concrètement ?

Sujet résolu
    13 avril 2017 à 10:30:48

    Bonjour,

    Ce débat est intéressant, on en vient à se demander ce qu’est un langage et une norme. Je me permets de donner mon avis :p

    Lynix a écrit:

    Un langage vient avec sa norme, évidemment que si tu ne respectes pas la norme du langage tu peux tout exploser, sauf qu'un langage n'existe pas sans sa norme. Faut arrêter les "et si" à un moment donné.

    C'est même plus que ça, un langage n'est rien d'autre qu'une norme. Chaque interpréteur a son propre langage et sa propre norme, défini à travers l'ensemble des mots et des constructions syntaxiques qu'il connaît et le sens qu'il leur donne. Cette norme n'est pas forcément fixée par un comité de normalisation au sens propre, mais pour être compris par son interpréteur, il est nécessaire de respecter l'ensemble des règles qu'il a posée.

    Si on est très pointilleux, on pourrait dire que deux interpréteurs comprenant différement un unique mot parlent deux langages différents, mais dans les faits, si la majorité du dictionnaire et de la syntaxique comprise par des interpréteurs sont identiques, on s'accorde à dire que c'est le même langage.

    Le comité de normalisation permet de faire sortir, parmi toutes les variations minimes de syntaxe comprise par chaque interpréteur qui sont autant de langages différents, un langage standard, les autres devenant ainsi des "dialectes" du langage principal. Le problème étant alors qu'un langage sans standard n'est pas vraiment un langage, mais une famille de langage variant autour d'une base forte.

    De fait, comparer deux langages avec standard a du sens, on compare les standard, alors que si on compare avec un "langage" à multiples implémentations, on peut comprendre la comparaison différement selon que l'on compare les variations les plus communément utilisées où les variations les plus avantageuses dans un certains contexte. Pour faire un parallèle avec les langages parlés, c'est comme si on partait de l'interrogation "un texte en anglais est-il en moyenne plus court qu'un texte en français ?". Les deux langues ont des standard (et encore, c'est défini par pays), ce qui permet de les comparer objectivement. Mais si elles n'en avaient pas, on comparerait quoi ? Le dialecte du sud-ouest avec l'anglais de Londres ? L'anglais américain avec le français de Belgique ?

    On en arrive à comparer des choses non comparables sans plus de contexte. Si on dit "C++ est plus rapide que Python", on compare un langage standard à une famille de langages très très semblables, chacun possédant une norme implicitement définie par les interpréteurs. Est-ce qu'on prend la norme implicite la plus couramment utilisée ? La plus rapide ?

    • Partager sur Facebook
    • Partager sur Twitter
      13 avril 2017 à 10:47:38

      De toute façon, la plupart des définitions de langages, en particulier les mainstreams, sont inconsistantes. Donc on peut bien faire ce qu'on veut derrière. Sans parler de la notion d'optimisation qui formellement impose seulement de sortir un sous-ensemble des comportements définis par le programme.

      Ah et il faut pas oublier que toutes ces suppositions sont vraies pour des programmes qui sont intégralement sémantiquement corrects, et dieu sait qu'il y en a pas des masses en vrai.

      -
      Edité par Ksass`Peuk 13 avril 2017 à 11:24:33

      • Partager sur Facebook
      • Partager sur Twitter

      Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C

        13 avril 2017 à 11:48:50

        Ksass`Peuk a écrit:

        De toute façon, la plupart des définitions de langages, en particulier les mainstreams, sont inconsistantes. Donc on peut bien faire ce qu'on veut derrière. Sans parler de la notion d'optimisation qui formellement impose seulement de sortir un sous-ensemble des comportements définis par le programme.

        A ce point-là ? J'avoue que j'ai aucune idée de la manière dont sont pensées les définitions des langages, mais j'aurais imaginé qu'un langage destiné à communiquer avec quelque chose d'aussi cadré et obtus qu'une machine devrait au contraire être très complet dans sa définition et sa syntaxe. Il y a bien des UB en C et C++, mais déjà définir le fait qu'on a un UB est en soi la définition d'un comportement normé.

        Mais est-ce que ça implique que chaque compilateur définit dans son implémentation des comportements qui ne sont pas normés par le langage, ou est-ce que c'est clairement laissé "au hasard", et que les comportements non normés sont générés "au pif" en découlant d'autres comportements normés et d'un contexte extérieur propre à la machine ?

        • Partager sur Facebook
        • Partager sur Twitter
          13 avril 2017 à 12:33:31

          L'UB n'a de sens que normatif, la norme dit à celui qui implémente, dans ce cas là tu fais ce que tu veux, et celui qui implémente choisit comment il va gérer l'UB. C'est une UB dans la mesure où la norme ne prescrit pas de comportement particulier, et donc dit aux utilisateurs attention, si vous vous trouvez dans ce schéma, le comportement dépendra du compilateur/interpréteur/os/machine/âge du capitaine/vitesse du vent...
          • Partager sur Facebook
          • Partager sur Twitter
          Mettre à jour le MinGW Gcc sur Code::Blocks. Du code qui n'existe pas ne contient pas de bug
            13 avril 2017 à 13:10:51

            RaymoAisla a écrit:

            A ce point-là ? J'avoue que j'ai aucune idée de la manière dont sont pensées les définitions des langages, mais j'aurais imaginé qu'un langage destiné à communiquer avec quelque chose d'aussi cadré et obtus qu'une machine devrait au contraire être très complet dans sa définition et sa syntaxe.

            Ah bah ça devrait ouais. Le problème c'est que quand le travail d'implémentation de CompCert a été réalisé sur C, c'était pas très joyeux en réalité. C++ ne doit pas être beaucoup mieux (puisqu'il y a déjà une bonne partie de C dedans et tout un paquet de bordel en plus) et là on parle de deux langages qui ont été énormément étudiés sur un plan formel. Le problème c'est que tout ça n'est très généralement pas écrit formellement. C'est de l'anglais, une langue naturelle, par nature ce n'est pas précis, et en plus là, c'est gros. Donc on peut très bien avoir un corner-case quelque part qui dit "si on a A alors on fait B" et puis plus tard "si on a C, alors on fait D", avec B et D différent et pas de bol, des cas particuliers de A sont dans C. Paf, inconsistance.

            Les UB ne sont pas un vrai problème, les développeurs n'ont qu'à écrire correctement.

            • Partager sur Facebook
            • Partager sur Twitter

            Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C

              13 avril 2017 à 18:02:21

              Si j'écris ça :

              int main()
              {
                std::vector<int> v{};
                v.reserve(2);
                v.resize(1);
                v[1] = 5;
                std::cout << v[1] << std::endl;
                return 0;
              }

              Quelle est la probabilité que ça donne 5 en sortie ? C'est un UB de la norme car tu es hors limites du vecteur. Cependant, tu as dit que tu voulais ajouter jusqu'à 2 éléments potentiellement juste avant. Pourtant, je pense qu'aucun compilateur ne va faire un code en release qui va te renvoyer un résultat différent de 5, à moins de vraiment le vouloir. Un UB est là pour dire "en tant que développeur, tu ne dois jamais y aller" et "en tant que compilateur, tu as le droit de renvoyer ce qui t'arrange dans ce cas pour optimiser".

              -
              Edité par anolya 13 avril 2017 à 18:03:11

              • Partager sur Facebook
              • Partager sur Twitter
                13 avril 2017 à 18:13:44

                Dans ce cas-ci, le fait de fonctionner est le comportement indéterminé :D
                • Partager sur Facebook
                • Partager sur Twitter

                Mes articles | Nazara Engine | Discord NaN | Ma chaîne Twitch (programmation)

                  14 avril 2017 à 0:16:53

                  Là, il ne s'agit pas d'une UB, mais carrément d'une violation des règles, la norme dit que l'argument passé à l'opérateur [] de vector doit être  >=0 et < size() et elle précise que vector n'est pas responsable de la vérification des bornes lorsqu'on utilise [], si on veut donner à vector la responsabilité de la vérification des bornes, c'est la très critiquée fonction at() qu'il faut employer.

                  une véritable UB serait plutôt quelque chose comme ça:

                  auto j = ++i--;

                  que valent  i et j? Là, il y a un vrai problème, les opérateurs ++ et -- ont la même priorité selon la norme, seulement dans la vraie vie il va falloir choisir ++ en premier -- après ou bien l'inverse, les deux options sont parfaitement recevables, vous trouverez autant d'argument pour ++ d'abord que pour -- d'abord, alors la norme dit que c'est une UB et recommande d'utiliser des parenthèses pour préciser l'ordre d'application des deux opérateurs. Cet exemple est un peu grillé, la plupart des compilateurs c++ n'acceptent probablement plus ce type code et produisent une erreur pour forcer le programmeur à clarifier son intention.

                  -
                  Edité par int21h 14 avril 2017 à 0:45:32

                  • Partager sur Facebook
                  • Partager sur Twitter
                  Mettre à jour le MinGW Gcc sur Code::Blocks. Du code qui n'existe pas ne contient pas de bug
                    14 avril 2017 à 8:35:27

                    Il y a bien longtemps, j'avais assisté à des discussions d'experts (sur fclc++ probablement) où l'on discutait de la différence entre un undefined behaviour (plantage quasi assuré) et un unspecified behaviour (liberté aux fournisseurs de choisir ce qui sera fait).

                    Jusqu'à présent, j'emploie UB dans le 1er sens. Et dans mes souvenirs, --i++, c'est juste du unspecified, NB je peux me tromper. J'ai l'impression qu'au fil du temps la différence entre les deux c'est perdue pour plus d'un guru/wanabe-guru.

                    • Partager sur Facebook
                    • Partager sur Twitter
                    C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                      14 avril 2017 à 8:49:03

                      Normalement undefined, ça veut dire ce que ça veut dire : ça peut faire n'importe quoi et les compilateurs ne sont pas obligés de lui donner une sémantique ni à respecter la sémantique du reste du programme, car en résultante le programme n'a plus de sémantique. Pour unspecified, wikipedia a l'air d'indiquer que c'est équivalent à "implementation defined", ce qui me semble aussi le plus probable mais je n'en mettrais pas ma main à couper.

                      • Partager sur Facebook
                      • Partager sur Twitter

                      Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C

                        14 avril 2017 à 10:55:57

                        Ce qui est hors normes n'est-il pas implicitement un UB ?

                        La norme dit ce que l'on peut faire et qui doit être correctement interprété par le compilateur. Cependant, certains compilateurs ajoutent des mots-clés pour l'aider. gcc a par exemple __builtin_expect pour indiquer que la valeur calculée est probablement celle donnée en 2ème paramètre. 

                        -
                        Edité par anolya 14 avril 2017 à 10:56:15

                        • Partager sur Facebook
                        • Partager sur Twitter
                          14 avril 2017 à 11:02:56

                          anolya a écrit:

                          Ce qui est hors normes n'est-il pas implicitement un UB ?

                          Ben ça dépend de ce que tu appelles "hors norme". Typiquement, le type de retour de std::bind est "unspecified" mais les concepteurs des implémentations réelles doivent choisir un type qui match les obligations imposées par la norme à propos du résultat. En ce sens, le type lui même n'est pas explicitement forcé par la norme mais doit correspondre à un comportement correct ou bout du compte.

                          • Partager sur Facebook
                          • Partager sur Twitter

                          Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C

                            14 avril 2017 à 14:29:59

                            Je lisais aussi "unspecified behaviour" comme "implementation defined behaviour". C'est bien la même idée.
                            • Partager sur Facebook
                            • Partager sur Twitter
                            C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                              14 avril 2017 à 18:21:51

                              Il y a eu un article de LLVM sur les UB. Et une page sur cppreference : http://en.cppreference.com/w/cpp/language/ub (le lien vers les articles de LLVM en bas). Dans la norme, c'est definie dans 1.3.

                              1.3.11 [defns.ill.formed] ill-formed program

                              program that is not well-formed (1.3.29)

                              1.3.12 [defns.impl.defined] implementation-defined behavior

                              behavior, for a well-formed program construct and correct data, that depends on the implementation and that each implementation documents

                              (...)

                              1.3.27 [defns.undefined] undefined behavior

                              behavior for which this International Standard imposes no requirements [ Note: Undefined behavior may be expected when this International Standard omits any explicit definition of behavior or when a program uses an erroneous construct or erroneous data. Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message). Many erroneous program constructs do not engender undefined behavior; they are required to be diagnosed. Evaluation of a constant expression never exhibits behavior explicitly specified as undefined (5.20). — end note ]

                              1.3.28 [defns.unspecified] unspecified behavior

                              behavior, for a well-formed program construct and correct data, that depends on the implementation [ Note: The implementation is not required to document which behavior occurs. The range of possible behaviors is usually delineated by this International Standard. — end note ]

                              1.3.29 [defns.well.formed] well-formed program

                              C++ program constructed according to the syntax rules, diagnosable semantic rules, and the one-definition rule (3.2).

                              • Partager sur Facebook
                              • Partager sur Twitter
                                15 avril 2017 à 19:20:47

                                Ces définitions sont intéressantes, je pense que ++i-- est un undefined behavior au sens Undefined behavior may be expected when this International Standard omits any explicit definition of behavior ici, l'ordre d'application des deux opérateurs va avoir un impact sur le résultat, le comportement sera forcément différent selon qu'on applique d'abord ++ ou d'abord --. cela ne relève à mon avis pas de l'implémentation-defined, ni de l'unspecified, parce que l'évaluation produira un résultat différent. Si je reprends l'exemple du bind de Ksaas`Peuk, peut importe comment on va sortir le résultat, l'important c'est qu'a la sortie, std::bind va retourner un truc assimilable à une fonction possédant une signature donnée, et ce quelque soit l'implémentation, là on est dans l'unspecified/implementation-defined.

                                -
                                Edité par int21h 15 avril 2017 à 19:33:25

                                • Partager sur Facebook
                                • Partager sur Twitter
                                Mettre à jour le MinGW Gcc sur Code::Blocks. Du code qui n'existe pas ne contient pas de bug
                                  15 avril 2017 à 23:28:38

                                  Dans le cas de ++i--, le mot cl" est "séquence point": http://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                  C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                                    16 avril 2017 à 11:23:48

                                    Quel endroit dans la norme indique que operator++(int) et operator++() ont la même priorité ? cpprefence ne donne pas ça. Ca serait bien de le leur indiquer s'ils font fausse route : http://en.cppreference.com/w/cpp/language/operator_precedence

                                    D'ailleurs, avec ça, on peut dire que le résultat ++i-- donnera i+1 et que i deviendra i-1.

                                    EDIT : en fait non, il y a des histoires de rvalue et lvalue. i-- renvoie une rvalue donc on ne peut pas exécuter operator++() par la suite. Le problème est résolu.

                                    -
                                    Edité par anolya 16 avril 2017 à 11:32:39

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      16 avril 2017 à 19:48:54

                                      Les priorités se déduisent de la grammaire si mes souvenirs sont bons. Dit autrement il n'y a rien de tel dans la norme
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                      C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                                        16 avril 2017 à 22:38:38

                                        La grammaire donne l'ordre de priorité :

                                        a -> a++ | b
                                        b -> ++b | c
                                        c -> (a)



                                        -
                                        Edité par anolya 16 avril 2017 à 22:40:31

                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          17 avril 2017 à 15:00:04

                                          Comme l'a dit lmghs, c'est une affaire de séquence ;) 

                                          1) If a side effect on a scalar object is unsequenced relative to another side effect on the same scalar object, the behavior is undefined.

                                          2) If a side effect on a scalar object is unsequenced relative to a value computation using the value of the same scalar object, the behavior is undefined.

                                          Et sur les séquences:

                                          1) Between the previous and next sequence point a scalar object must have its stored value modified at most once by the evaluation of an expression, otherwise the behavior is undefined.

                                          2) Between the previous and next sequence point, the prior value of a scalar object that is modified by the evaluation of the expression, must be accessed only to determine the value to be stored. If it is accessed in any other way, the behavior is undefined.

                                           source

                                          L'article entier mérite d'être lu ;)

                                          mon ++i-- n'entre peut être pas là dedans, mais il est assez représentatif de trucs vraiment suspect que le compilateur peut accepter et qui mèneront (peut être) à une UB (sans aller jusqu’à une erreur de programmation plus ou moins involontaire/délibérée). Peut être une façon de dire qu'il  est toujours préférable de privilégier un code clair et lisible et peut être d'éviter d'aller jouer avec les limites du langage, c++ est bien assez riche pour qu'il soit besoin d'aller chercher dans ses ambiguités :)

                                          -
                                          Edité par int21h 17 avril 2017 à 15:23:56

                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                          Mettre à jour le MinGW Gcc sur Code::Blocks. Du code qui n'existe pas ne contient pas de bug
                                            21 mars 2024 à 17:23:16


                                            Je déterre ce vieux topic car je ne peux pas résister à répondre à cela :

                                            bacelar a écrit:

                                            Rien de théorique dans ma remarque, confère le passage Assembleur - Compilateur C.

                                            Les premiers compilateurs, fait en assembleur, générait du code bien moins performant que de l'assembleur fait main.

                                            Maintenant, qui irait faire de l'assembleur à la main pour faire plus vite que l'optimiseur d'un compilateur C ou C++ ?

                                            Et bien justement, ça se fait. La librairie Intel MKL (Math Kernel Library), dédiée au calcul scientifique, domaine dans lequel les performances sont souvent un critère primordial, a des morceaux écrits directement en assembleur. Et ceci bien que le compilateur Intel soit plutôt bon en optimisation. La plupart du temps un compilateur C fera aussi bien que de l'assembleur à la main, mais parfois non.
                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              21 mars 2024 à 17:32:55

                                              C'est très particulier ici pour la MKL. Certes il y a de l'ASM dedans, mais aussi du CPU-dispatching. C'est à dire qu'une même fonction peut être écrite 15 fois pour toutes les combinaisons d'instructions étendues et/ou d'architecture trouvées.

                                              Donc oui, ils savent que c'est optimisé pour leurs procs à eux (AMD... c'est une autre histoire). Et assez normal. Même s'ils participent à clang/gcc, il reste des détails connus d'eux seul et des faiblesses dans les auto-vectorisations.

                                              -
                                              Edité par lmghs 21 mars 2024 à 18:28:54

                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                              C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                                                21 mars 2024 à 17:48:22

                                                PierU a écrit:

                                                Et bien justement, ça se fait.
                                                (...)
                                                La plupart du temps un compilateur C fera aussi bien que de l'assembleur à la main, mais parfois non.

                                                Oui, dans l'absolu, on peut jamais dire jamais.

                                                Mais dans la réalité, il faut considérer les coûts liés a de telles optimisations :

                                                - en termes de compétences a acquérir pour les devs

                                                - en termes de maintenance sur le long terme (code plus compliqué, plus risqué, moins de devs qui peuvent travailler dessus)

                                                - de temps de dev et de test, en particulier sur tous les hardwares

                                                - et surtout, les gains estimé et réels

                                                Dans la très grande majorité des cas, le gain ne seront pas assez significatifs pour justifier de former les devs et de prendre le temps pour dev et tester ce type d'approche.

                                                Ceux qui ont le temps, les compétences et l'intérêt (économique souvent) de faire ce genre d'approche, c'est justement les devs qui bossent pour les constructeurs de matos (Intel, NVIDIA, etc), de systèmes (Microsoft, Apple, etc) et de compilateurs (qui sont souvent les mêmes devs que précédemment). 

                                                Pour les devs "moyens" (ou même expert, mais pas dans ces domaines), ils ne battront pas le boulot qui est fait par ces devs experts.

                                                -
                                                Edité par gbdivers 21 mars 2024 à 17:49:06

                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                  22 mars 2024 à 13:54:24

                                                  Il me semble qu'IBM faisait la promotion de ses compilateurs FORTRAN de la vieille époque (60's) en affirmant que le code généré était plus plus efficace que la production habituelle des programmeurs en langage d'assemblage (tests à l'appui). D'où gain sur les deux tableaux : efficacité du programme résultant, heures de travail pour l'écrire.

                                                  Ce n'est pas une question de langage ayant servi à écrire le compilateur.

                                                  Du reste, un facteur à prendre en compte, c'est que quand on a écrit un code assembleur d'une certaine taille, on n'a pas trop envie de tout revoir pour introduire une modif  qui touche à beaucoup de code. Donc même si on est parti avec du code "optimal", il ne le reste pas à cause des modifs introduites pour la maintenance évolutive.  Alors que le compilateur, il est pas fainéant, il retraduit tout et applique (croisons les doigts) les optimisations qu'il trouve.

                                                  Ps voir l'article "histoire de fortran i, ii et iii"  

                                                  https://dl.acm.org/doi/10.1145/800025.1198345 par John Backus lui-même. La qualité du code génèré était un objectif  dès la conception du langage. Il y avait déjà des "systèmes de programmation automatique" qui certes acceleraient le développement, mais fournissaient du code beaucoup plus lent. Et ça ne plaisait pas trop, il était indispensable de se démarquer. Les techniques d'optimisation inventées à cette occasion (allocation de registres, optimisation de boucles etc) faisaient mieux que la plupart des programmeurs.

                                                  -
                                                  Edité par michelbillaud 23 mars 2024 à 9:41:48

                                                  • Partager sur Facebook
                                                  • Partager sur Twitter

                                                  Différence entre C, C# et C++ ?

                                                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                  • Editeur
                                                  • Markdown