und - Kann Code, der sowohl in C als auch in C++ gültig ist, ein unterschiedliches Verhalten erzeugen, wenn er in jeder Sprache kompiliert wird?




unterschied c++ c# (11)

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

#include <stdio.h>

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

In C bedeutet auto lokale Variable. In C90 ist es in Ordnung, die Variable oder den Funktionstyp wegzulassen. Es ist standardmäßig auf int . In C ++ bedeutet 11 auto etwas ganz anderes, es weist den Compiler an, den Typ der Variablen aus dem Wert abzuleiten, mit dem sie initialisiert wurde.

C und C ++ haben viele Unterschiede, und nicht jeder gültige C-Code ist ein gültiger C ++ - Code.
(Mit "gültig" meine ich Standardcode mit definiertem Verhalten, dh nicht implementierungsspezifisch / undefiniert / etc.)

Gibt es ein Szenario, in dem ein Code, der sowohl in C als auch in C ++ gültig ist, zu einem anderen Verhalten führen würde, wenn er mit einem Standardcompiler in jeder Sprache kompiliert wird?

Um es zu einem vernünftigen / nützlichen Vergleich zu machen (Ich versuche etwas praktisch Nützliches zu lernen, nicht zu versuchen, offensichtliche Lücken in der Frage zu finden), nehmen wir an:

  • Nichts Preprozessor-bezogen (was bedeutet, dass keine Hacks mit #ifdef __cplusplus , Pragmas, etc.)
  • Alles, was in der Implementierung definiert ist, ist in beiden Sprachen gleich (zB numerische Grenzen, etc.)
  • Wir vergleichen relativ aktuelle Versionen jedes Standards (zB C ++ 98 und C90 oder später)
    Wenn die Versionen wichtig sind, geben Sie bitte an, welche Versionen von beiden unterschiedliche Verhaltensweisen haben.

Das Folgende, gültig in C und C ++, wird (höchstwahrscheinlich) zu verschiedenen Werten in i in C und C ++ führen:

int i = sizeof('a');

Eine Erklärung des Unterschieds finden Sie unter Größe des Zeichens ('a') in C / C ++ .

Ein anderer aus diesem Artikel :

#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;
}

Ein anderes Beispiel, das ich noch nicht erwähnt habe, das hebt einen Präprozessor-Unterschied hervor:

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

Dies gibt "falsch" in C und "wahr" in C ++ aus. In C wird jedes nicht definierte Makro mit 0 ausgewertet. In C ++ gibt es eine Ausnahme: "true" ergibt 1.


Ein weiterer, der im C ++ Standard aufgeführt ist:

#include <stdio.h>

int x[1];
int main(void) {
    struct x { int a[2]; };
    /* size of the array in C */
    /* size of the struct in C++ */
    printf("%d\n", (int)sizeof(x)); 
}

Eine andere sizeof Trap: boolesche Ausdrücke.

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

Er entspricht in C der sizeof(int) , da der Ausdruck vom Typ int , in C ++ jedoch typischerweise 1 ist (obwohl dies nicht erforderlich ist). In der Praxis sind sie fast immer verschieden.


Für C ++ vs. C90 gibt es mindestens eine Möglichkeit, ein unterschiedliches Verhalten zu erhalten, bei dem keine Implementierung definiert ist. C90 hat keine einzeiligen Kommentare. Mit etwas Vorsicht können wir daraus einen Ausdruck mit völlig anderen Ergebnissen in C90 und C ++ erstellen.

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

In C ++ ist alles vom // bis zum Ende der Zeile ein Kommentar, also funktioniert das wie folgt:

int a = 10 + 3;

Da C90 keine einzeiligen Kommentare hat, ist nur der /* comment */ ein Kommentar. Die erste / und die zweite sind beide Teile der Initialisierung, also kommt es zu:

int a = 10 / 2 + 3;

Also, ein korrekter C ++ - Compiler gibt 13, aber einen korrekten C-Compiler 8. Natürlich habe ich hier nur willkürliche Zahlen gewählt - Sie können andere Zahlen verwenden, wie Sie es für richtig halten.


Inline-Funktionen in C haben standardmäßig einen externen Gültigkeitsbereich, während dies in C ++ nicht der Fall ist.

Das Kompilieren der folgenden zwei Dateien würde das "Ich bin Inline" im Falle von GNU C aber nichts für C ++ drucken.

Datei 1

#include <stdio.h>

struct fun{};

int main()
{
    fun();  // In C, this calls the inline function from file 2 where as in C++
            // this would create a variable of struct fun
    return 0;
}

Datei 2

#include <stdio.h>
inline void fun(void)
{
    printf("I am inline\n");
} 

Außerdem behandelt C ++ implizit jedes const global als static sofern es nicht ausdrücklich extern deklariert ist, im Gegensatz zu C, in dem extern der Standardwert ist.


Per C ++ 11 Standard:

ein. Der Komma-Operator führt eine Lvalue-to-Rvalue-Konvertierung in C, aber nicht in C ++ durch:

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

In C ++ ist der Wert dieses Ausdrucks 100 und in C ist dies sizeof(char*) .

b. In C ++ ist der Typ des Enumerators seine Enumeration. In C ist der Typ des Enumerators int.

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

Dies bedeutet, dass sizeof(int) möglicherweise nicht gleich der sizeof(E) .

c. In C ++ nimmt eine mit der Liste der leeren Parameter deklarierte Funktion keine Argumente an. In C bedeutet die Liste der leeren Parameter, dass Anzahl und Typ der Funktionsparameter unbekannt sind.

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

Die C ++ Programmiersprache (3. Edition) gibt drei Beispiele:

  1. sizeof ('a'), wie @Adam Rosenfield erwähnt;

  2. // Kommentare werden verwendet, um versteckten Code zu erstellen:

    int f(int a, int b)
    {
        return a //* blah */ b
            ;
    }
    
  3. Strukturen usw., die Dinge in anderen Bereichen verbergen, als in Ihrem Beispiel.


#include <stdio.h>

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

In C wird gedruckt, was auch immer der Wert von sizeof(int) auf dem aktuellen System ist, was in den meisten heute üblichen Systemen typischerweise 4 ist.

In C ++ muss dies 1 drucken.


struct abort
{
    int x;
};

int main()
{
    abort();
    return 0;
}

Gibt mit dem Exit-Code 0 in C ++ oder 3 in C zurück.

Dieser Trick könnte wahrscheinlich verwendet werden, um etwas Interessanteres zu tun, aber ich konnte mir keinen guten Weg vorstellen, einen Konstruktor zu erstellen, der für C schmackhaft wäre. Ich habe versucht, ein ähnlich langweiliges Beispiel mit dem Kopierkonstruktor zu machen, das ein Argument zulassen würde übergeben werden, wenn auch nicht portabel:

struct exit
{
    int x;
};

int main()
{
    struct exit code;
    code.x=1;

    exit(code);

    return 0;
}

VC ++ 2005 weigerte sich jedoch, dies im C ++ - Modus zu kompilieren, und beschwerte sich darüber, wie "Exit-Code" neu definiert wurde. (Ich denke, das ist ein Compiler-Fehler, es sei denn, ich habe plötzlich vergessen zu programmieren.) Er wurde mit einem Prozess-Exit-Code von 1 beendet, obwohl er als C kompiliert wurde.





c