web-dev-qa-db-fra.com

Où C n'est-il pas un sous-ensemble de C ++?

J'ai lu dans beaucoup de livres que C est un sous-ensemble de C++.

Certains livres disent que C est un sous-ensemble de C++, sauf pour les petits détails.

Quels sont les cas où le code sera compilé en C, mais pas en C++?

110
n00ki3

Si vous comparez C89 avec C++ alors voici deux ou trois choses

Aucune définition provisoire en C++

int n;
int n; // ill-formed: n already defined

int [] et int [N] non compatibles (pas de types compatibles en C++)

int a[1];
int (*ap)[] = &a; // ill-formed: a does not have type int[]

Pas de style de définition de fonction K&R

int b(a) int a; { } // ill-formed: grammar error

La structure imbriquée a une portée de classe en C++

struct A { struct B { int a; } b; int c; };
struct B b; // ill-formed: b has incomplete type (*not* A::B)

Aucun int par défaut

auto a; // ill-formed: type-specifier missing

C99 ajoute beaucoup d'autres cas

Pas de traitement spécial des spécificateurs de déclaration dans les dimensions de tableau des paramètres

// ill-formed: invalid syntax
void f(int p[static 100]) { }

Pas de tableaux de longueur variable

// ill-formed: n is not a constant expression
int n = 1;
int an[n];

Aucun membre flexible du tableau

// ill-formed: fam has incomplete type
struct A { int a; int fam[]; }; 

Aucun qualificatif de restriction pour aider l'analyse d'alias

// ill-formed: two names for one parameter?
void copy(int *restrict src, int *restrict dst);
132

En C, sizeof('a') est égal à sizeof(int).

En C++, sizeof('a') est égal à sizeof(char).

48
Naveen

C++ a également de nouveaux mots clés. Ce qui suit est du code C valide mais ne se compilera pas sous C++:

int class = 1;
int private = 2;
int public = 3;
int virtual = 4;
36
Graeme Perrow

Il y a plein de choses. Juste un exemple simple (cela devrait suffire pour prouver que C n'est pas un sous-ensemble approprié de C++):

int* test = malloc(100 * sizeof(int));

devrait compiler en C mais pas en C++.

20
Mehrdad Afshari

En C++, si vous déclarez un struct, union ou enum, son nom est immédiatement accessible sans aucun qualificatif:

struct foo { ... };
foo x; // declare variable

En C, cela ne fonctionnera pas, car les types ainsi déclarés vivent dans leurs propres espaces de noms distincts. Ainsi, vous devez écrire:

struct foo { ... };
struct foo x; // declare variable

Remarquez la présence de struct sur la deuxième ligne. Vous devez faire de même pour union et enum (en utilisant leurs mots-clés respectifs), ou utilisez l'astuce typedef:

typedef struct { ... } foo;
foo x; // declare variable

Par conséquent, vous pouvez avoir plusieurs types de types différents nommés de la même manière en C, car vous pouvez lever l'ambiguïté:

struct foo { ... };
typedef enum { ... } foo;

struct foo x;
foo y;

En C++, cependant, alors que vous pouvez préfixer un nom struct avec le mot clé struct chaque fois que vous le référencez, les espaces de noms sont fusionnés et donc l'extrait C ci-dessus n'est pas valide. D'un autre côté, C++ fait spécifiquement une exception pour autoriser un type et un typedef pour ce type à avoir le même nom (évidemment sans effet), pour permettre l'utilisation de l'astuce typedef inchangée par rapport à C.

16
Pavel Minaev

Cela dépend également de la variété de C que vous utilisez. Stroustrup a rendu C++ aussi compatible que possible, et plus compatible avec les normes 1989 ANSI et ISO 1990, et la version 1995 n'a rien changé. Le comité C est allé dans une direction quelque peu différente avec la norme de 1999, et le comité C++ a changé la prochaine norme C++ (probablement l'année prochaine) pour se conformer à certains des changements.

Stroustrup répertorie les incompatibilités avec C90/C95 dans l'annexe B.2 de "The C++ Programming Language", Special Edition (qui est la 3e édition avec du matériel ajouté):

'a' Est un int en C, un char en C++.

La taille d'une énumération est int en C, pas nécessairement en C++.

C++ a des commentaires // À la fin de la ligne, pas C (bien que ce soit une extension courante).

En C++, une définition struct foo { Place foo dans l'espace de noms global, tandis qu'en C il faudrait l'appeler struct foo. Cela permet à une définition struct d'occulter un nom dans une portée externe, et a quelques autres conséquences. En outre, C autorise une plus grande portée pour les définitions struct et les autorise dans les déclarations de type de retour et de type d'argument.

C++ est plus compliqué sur les types en général. Il ne permettra pas l'attribution d'un entier à un enum et les objets void * Ne peuvent pas être affectés à d'autres types de pointeurs sans transtypage. En C, il est possible de fournir un initialiseur trop large (char name[5] = "David" Où C supprimera le caractère nul de fin).

C89 autorisait implicitement int dans de nombreux contextes, contrairement à C++. Cela signifie que toutes les fonctions doivent être déclarées en C++, alors qu'en C89, il était souvent possible de s'en tirer en supposant int pour tout ce qui est applicable dans la déclaration de fonction.

En C, il est possible de sauter de l'extérieur d'un bloc vers l'intérieur à l'aide d'une instruction étiquetée. En C++, cela n'est pas autorisé s'il saute une initialisation.

C est plus libéral dans les liens externes. En C, une variable globale const est implicitement extern, et ce n'est pas vrai en C++. C permet à un objet de données global d'être déclaré plusieurs fois sans extern, mais ce n'est pas vrai en C++.

De nombreux mots clés C++ ne sont pas des mots clés en C, ou sont #define D dans les en-têtes C standard.

Il existe également des fonctionnalités plus anciennes de C qui ne sont plus considérées comme un bon style. En C, vous pouvez déclarer une fonction avec les définitions d'arguments après la liste des arguments. En C, une déclaration comme int foo() signifie que foo() peut prendre n'importe quel nombre de n'importe quel type d'arguments, tandis qu'en C++ c'est équivalent à int foo(void).

Cela semble couvrir tout de Stroustrup.

8
David Thornley
#include <stdio.h>

int new (int n) {
    return n/2;
}

int main(void) {
    printf("%d\n", new(10));
    return 0;
}

Voir aussi l'entrée C++ FAQ .

4
Sinan Ünür

Je pense que la plus grande différence est qu'il s'agit d'un fichier source C valide:

int main()
{
    foo();
}

Notez que je n'ai déclaré foo nulle part.

Mis à part les différences de langage, C++ apporte également quelques modifications à la bibliothèque héritée de C, par exemple certaines fonctions renvoient const char * au lieu de char *.

4
Daniel Earwicker

Si vous utilisez gcc, vous pouvez utiliser l'avertissement -Wc++-compat pour vous donner des avertissements sur le code C qui est en quelque sorte douteux en C++. Il est actuellement utilisé dans gcc lui-même et s'est beaucoup amélioré récemment (essayez peut-être une version nocturne pour obtenir le meilleur possible).

(Cela ne répond pas strictement à la question, mais les gens pourraient l'aimer).

4
Paul Biggar

Un certain nombre de réponses ici couvrent les différences de syntaxe qui entraîneraient l'échec des compilateurs C++ sur le code source C89 (ou C99). Cependant, il existe des différences linguistiques subtiles qui sont légales dans les deux langues mais qui produiraient un comportement différent. La différence sizeof (char) mentionnée par Naveen en est un exemple, mais Écrivez un programme qui affichera "C" s'il est compilé en tant que programme (ANSI) C et "C++" s'il est compilé en tant que programme C++ en répertorie quelques autres.

1
jamesdlin