Il y a un tas d'incompatibilités qui ont été autour depuis des siècles (C90 ou plus tôt), ainsi que d'un tas de fonctionnalités intéressantes dans C99 et C11. Ce sont tous sur le dessus de ma tête.
// Valid C
int *array = malloc(sizeof(*array) * n);
// Valid C and valid C++, extra typing, it's always extra typing...
int *array = (int *) malloc(sizeof(*array) * n);
// Valid C++
int *array = new int[n];
C99 est sympa et C programmeurs partout dans le monde devrait l'utiliser
Les nouvelles fonctionnalités en C99 sont très agréable pour la programmation en général. Blaise et restrict
ne le sont pas (à mon avis) ciblés pour un usage général, mais surtout pour apporter FORTRAN et numérique programmeurs de C (bien qu' restrict
aide à la autovectorizer). Depuis tout conforme programme qui utilise restrict
fonctionnera exactement de la même manière (mais peut-être pas aussi rapide) si vous #define restrict
en haut de la fiche, c'est pas une grosse affaire. VLAs sont assez rares dans la nature, il semble.
Flexible membres du groupe peut être sympa. Notez que ce ne sont PAS les mêmes que la longueur variable des tableaux! Les gens ont été en utilisant ce truc depuis des années, mais le soutien officiel signifie moins de frappe et il nous permet aussi de faire constantes au moment de la compilation. (L'ancien était d'avoir un tableau de taille 1, mais lors du calcul de la taille d'allocation est un véritable peine.)
struct lenstr {
unsigned length;
char data[];
};
// compile time constant
const struct lenstr hello = { 12, "hello, world" };
Désigné initialiseurs. Permet d'économiser beaucoup de la saisie.
struct my_struct { int a; char *b; int c; const char *d; };
struct my_struct x = {
.a = 15,
.d = "hello"
// implicitly sets b = NULL and c = 0
};
int hex_digits[256] = { ['0'] = 0, ['1'] = 1, ['2'] = 2, /* etc */ ['f'] = 15 };
L' inline
mot-clé se comporte différemment, vous pouvez choisir l'unité de traduction obtient un non-inline version d'une fonction déclarées en ligne par l'ajout d'une déclaration extern à cette unité.
Composé de littéraux.
struct point { float x; float y; };
struct point xy_from_polar(float r, float angle)
{
return (struct point) { cosf(angle) * r, sinf(angle) * r };
}
L' snprintf
fonction est probablement dans mon top 10 des plus utiles de la bibliothèque de fonctions en C. Il n'est pas seulement manquant à partir de C++, mais le MSVC runtime fournit uniquement une fonction appelée _snprintf
, ce qui n'est pas garanti pour ajouter un NUL de terminaison de la chaîne. (snprintf
est en C++11, mais encore remarquablement absent de la MSVC C runtime.)
Anonyme les structures et les syndicats (C11, mais GCC extension depuis toujours) (anonyme syndicats sont apparemment en C++03, pas de MSVC support en C mode):
struct my_value {
int type;
union {
int as_int;
double as_double;
}; // no field name!
};
Comme vous pouvez le voir, beaucoup de ces fonctions seulement vous faire économiser beaucoup de temps de frappe (composé de littéraux), ou de rendre les programmes plus facile à déboguer (flexible membres du groupe), de le rendre plus facile pour éviter les erreurs (désigné initializers / oublier d'initialiser les champs de structure). Ce ne sont pas des changements radicaux.
Pour les différences sémantiques, je suis sûr que l'aliasing règles sont différentes, mais la plupart des compilateurs sont suffisamment malléable ces jours, je ne suis pas sûr comment vous pouvez construire un cas de test à démontrer. La différence entre le C et le C++ que tout le monde est atteint pour le vieux - sizeof('a')
expression, qui est toujours 1 pour le C++, mais généralement de 4 sur 32 bits, le système de climatisation. Mais personne ne se soucie de ce que sizeof('a')
est de toute façon. Toutefois, il existe certaines garanties dans le standard C99 qui codifient les pratiques existantes.
Prenez le code suivant. Il utilise un truc commun pour la définition des types d'union dans C sans perdre de l'espace de stockage supplémentaire. Je pense que c'est sémantiquement valide C99 et je pense que c'est sémantiquement douteux, C++, mais j'ai peut-être tort.
#define TAG_FUNKY_TOWN 5
struct object { int tag; };
struct funky_town { int tag; char *string; int i; };
void my_function(void)
{
struct object *p = other_function();
if (p->tag == TAG_FUNKY_TOWN) {
struct funky_town *ft = (struct funky_town *) p;
puts(ft->string);
}
}
C'est une honte, si. Le MSVC générateur de code est sympa, dommage qu'il n'y a pas C99 front-end.