Question Un code valide en C et C ++ peut-il produire un comportement différent lorsqu'il est compilé dans chaque langue?


C et C ++ ont de nombreuses différences, et tout le code C valide n'est pas un code C ++ valide.
(Par "valide", je veux dire un code standard avec un comportement défini, c'est-à-dire non spécifique à l'implémentation / non défini / etc.)

Y at-il un scénario dans lequel un morceau de code valide à la fois C et C ++ produirait différent comportement lorsqu'il est compilé avec un compilateur standard dans chaque langue?

Pour en faire une comparaison raisonnable / utile (j'essaie d'apprendre quelque chose d'utile, de ne pas essayer de trouver des failles évidentes dans la question), supposons:

  • Rien de pré-processeur lié (ce qui signifie pas de hacks avec #ifdef __cplusplus, pragmas, etc.)
  • Tout ce qui est défini par l'implémentation est le même dans les deux langues (par exemple, les limites numériques, etc.)
  • Nous comparons des versions raisonnablement récentes de chaque norme (par exemple, C ++ 98 et C90 ou plus tard)
    Si les versions comptent, veuillez indiquer quelles versions de chaque produit produisent un comportement différent.

597
2017-10-14 23:54


origine


Réponses:


Ce qui suit, valide en C et C ++, va (très probablement) donner des valeurs différentes i en C et C ++:

int i = sizeof('a');

Voir Taille du caractère ('a') en C / C ++ pour une explication de la différence.

Un autre de Cet article:

#include <stdio.h>

int  sz = 80;

int main(void)
{
    struct sz { char c; };

    int val = sizeof(sz);      // sizeof(int) in C,
                               // sizeof(struct sz) in C++
    printf("%d\n", val);
    return 0;
}

353
2017-10-14 23:57



Voici un exemple qui tire parti de la différence entre les appels de fonctions et les déclarations d'objets en C et C ++, ainsi que le fait que C90 permet l'appel de fonctions non déclarées:

#include <stdio.h>

struct f { int x; };

int main() {
    f();
}

int f() {
    return printf("hello");
}

En C ++ cela n'imprimera rien car un temporaire f est créé et détruit, mais en C90, il va imprimer hello car les fonctions peuvent être appelées sans avoir été déclarées.

Au cas où vous vous poseriez des questions sur le nom f étant utilisé deux fois, les normes C et C ++ le permettent explicitement, et pour faire un objet que vous avez à dire struct f pour désambiguïser si vous voulez la structure, ou laisser tomber struct si vous voulez la fonction.


453
2017-10-15 00:19



Pour C ++ et C90, il existe au moins une façon d'obtenir un comportement différent qui n'est pas défini par l'implémentation. C90 n'a pas de commentaires sur une seule ligne. Avec un peu de soin, nous pouvons l'utiliser pour créer une expression avec des résultats entièrement différents en C90 et en C ++.

int a = 10 //* comment */ 2 
        + 3;

En C ++, tout de la // à la fin de la ligne est un commentaire, donc cela fonctionne comme:

int a = 10 + 3;

Puisque C90 n'a pas de commentaires sur une seule ligne, seul le /* comment */ est un commentaire. La première / et le 2 sont les deux parties de l'initialisation, de sorte qu'il sort à:

int a = 10 / 2 + 3;

Ainsi, un compilateur C ++ correct donnera 13, mais un compilateur C correct 8. Bien sûr, je viens de choisir des nombres arbitraires ici - vous pouvez utiliser d'autres nombres comme bon vous semble.


400
2017-10-15 06:03



C90 vs. C ++ 11 (int contre. double):

#include <stdio.h>

int main()
{
  auto j = 1.5;
  printf("%d", (int)sizeof(j));
  return 0;
}

En C auto signifie variable locale. En C90, il est possible d'omettre le type de variable ou de fonction. Par défaut int. En C ++ 11 auto signifie quelque chose de complètement différent, il dit au compilateur d'inférer le type de la variable à partir de la valeur utilisée pour l'initialiser.


160
2017-10-15 01:42



Un autre exemple que je n'ai pas encore vu mentionné, celui-ci mettant en évidence une différence de préprocesseur:

#include <stdio.h>
int main()
{
#if true
    printf("true!\n");
#else
    printf("false!\n");
#endif
    return 0;
}

Cela affiche "false" en C et "true" en C ++ - En C, toute macro non définie est évaluée à 0. En C ++, il y a 1 exception: "true" évalue à 1.


107
2017-10-17 02:17



Par norme C ++ 11:

une. L'opérateur virgule effectue une conversion lvalue-à-valeur en C mais pas en C ++:

   char arr[100];
   int s = sizeof(0, arr);       // The comma operator is used.

En C ++, la valeur de cette expression sera 100 et en C ce sera sizeof(char*).

b. En C ++, le type d'énumérateur est son énumération. En C, le type d'énumérateur est int.

   enum E { a, b, c };
   sizeof(a) == sizeof(int);     // In C
   sizeof(a) == sizeof(E);       // In C++

Cela signifie que sizeof(int) peut ne pas être égal à sizeof(E).

c. En C ++, une fonction déclarée avec une liste de paramètres vide ne prend aucun argument. En C, la liste des paramètres vides signifie que le nombre et le type des paramètres de la fonction sont inconnus.

   int f();           // int f(void) in C++
                      // int f(*unknown*) in C

95
2017-10-15 00:48



Ce programme imprime 1 en C ++ et 0 en C:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int d = (int)(abs(0.6) + 0.5);
    printf("%d", d);
    return 0;
}

Cela arrive parce qu'il y a double abs(double) surcharge en C ++, donc abs(0.6) résultats 0.6 tandis qu'en C il retourne 0 à cause de la conversion implicite double-à-int avant d'invoquer int abs(int). En C, vous devez utiliser fabs travailler avec double.


44
2017-12-15 05:24



#include <stdio.h>

int main(void)
{
    printf("%d\n", (int)sizeof('a'));
    return 0;
}

En C, cela imprime quelle que soit la valeur de sizeof(int) est sur le système actuel, qui est généralement 4 dans la plupart des systèmes couramment utilisés aujourd'hui.

En C ++, ceci doit imprimer 1.


36
2018-02-23 23:21



Un autre sizeof trap: expressions booléennes.

#include <stdio.h>
int main() {
    printf("%d\n", (int)sizeof !0);
}

Cela équivaut à sizeof(int) en C, parce que l'expression est de type int, mais est généralement 1 en C ++ (bien que ce ne soit pas obligatoire). En pratique, ils sont presque toujours différents.


35
2017-10-15 11:46



Un vieux châtaigne qui dépend du compilateur C, ne reconnaissant pas les commentaires de fin de ligne C ++ ...

...
int a = 4 //* */ 2
        +2;
printf("%i\n",a);
...

22
2018-02-24 00:05



Le langage de programmation C ++ (3ème édition) donne trois exemples:

  1. sizeof ('a'), comme l'a mentionné @Adam Rosenfield;

  2. // commentaires utilisés pour créer du code caché:

    int f(int a, int b)
    {
        return a //* blah */ b
            ;
    }
    
  3. Structures etc. cacher des choses dans des étendues, comme dans votre exemple.


22
2018-02-24 00:07