Istnieje kilka niezgodności, które istnieją od wieków (C90 o r wcześniej), a także kilka naprawdę fajnych funkcji w C99 i C11. Te są z góry mojej głowy.
// 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 jest ładne i programistów C wszędzie powinniśmy używać go
nowych funkcji C99 są bardzo miłe dla ogólnego programowania. VLA i restrict
nie są (moim zdaniem) przeznaczone do ogólnego użytku, ale głównie do sprowadzania FORTRAN i programistów numerycznych do C (chociaż restrict
pomaga autovectorizer). Ponieważ każdy zgodny program, który używa restrict
nadal będzie działał dokładnie w ten sam sposób (ale prawdopodobnie nie tak szybko), jeśli na górze pliku znajduje się #define restrict
, to nie jest wielka sprawa. VLA są dość rzadkie na wolności, jak się wydaje.
Elastyczne elementy tablicy mogą być ładne. Pamiętaj, że NIE są to te same tablice o zmiennej długości! Ludzie używają tej sztuczki od lat, ale oficjalne wsparcie oznacza mniej pisania, a także pozwala nam tworzyć stałe w czasie kompilacji. (Starym sposobem było posiadanie tablicy wielkości 1, ale obliczenie wielkości alokacji jest prawdziwym problemem.)
struct lenstr {
unsigned length;
char data[];
};
// compile time constant
const struct lenstr hello = { 12, "hello, world" };
Wyznaczone inicjalizatory. Zapisuje dużo pisania.
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 };
inline
kluczowe zachowuje się inaczej, można wybrać, które tłumaczenie jednostka dostaje non-inline wersję funkcji zadeklarowanej inline dodając extern deklarację do tej jednostki.
Koncentrat literały.
struct point { float x; float y; };
struct point xy_from_polar(float r, float angle)
{
return (struct point) { cosf(angle) * r, sinf(angle) * r };
}
snprintf
funkcja jest prawdopodobnie w moim top 10 najbardziej przydatnych funkcji bibliotecznych w C. To nie tylko brakuje C++, ale runtime MSVC zapewnia tylko funkcję o nazwie _snprintf
, która nie jest gwarantowane dodaj terminator NUL do ciągu. (snprintf
jest w C++ 11, ale nadal nieobecnosc od wykonywania MSVC C).
anonimowych struktury i związki (rozszerzenie C11, ale od zawsze GCC) (anonimowe związki są najwyraźniej w C + +03, brak wsparcia MSVC w trybie C):
struct my_value {
int type;
union {
int as_int;
double as_double;
}; // no field name!
};
Jak widać, wiele z tych funkcji tylko zaoszczędzić dużo pisanie (literały złożonych), lub dokonać programy łatwiejsze do debugowania (członkowie elastyczny array) , ułatwiają unikanie błędów (wyznaczają inicjatory/zapominając o inicjalizacji pól struktury). To nie są drastyczne zmiany.
Dla różnic semantycznych, jestem pewien, że reguły aliasingu są różne, ale większość kompilatorów jest wystarczająco wybaczająca w tych dniach Nie jestem pewien, jak skonstruować przypadek testowy do wykazania. Różnica między C i C++, do której wszyscy sięga, to stare wyrażenie sizeof('a')
, które zawsze jest 1 dla C++, ale zwykle 4 dla 32-bitowego systemu C. Ale nikomu nie zależy na tym, co jest sizeof('a')
. Istnieją jednak pewne gwarancje w standardzie C99, które kodyfikują istniejące praktyki.
Wprowadź następujący kod. Używa wspólnej sztuczki do definiowania typów związków w C bez marnowania dodatkowej pamięci. I think to jest semantycznie poprawne C99 i I myśleć jest to wątpliwy semantycznie C++, ale może się myliłem.
#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);
}
}
Ale szkoda. Generator kodu MSVC jest ładny, szkoda, nie ma front-end C99.
Czy C++ 11 obsługuje tablice o zmiennej długości? C99 ma, więc jeśli nie, to całkiem dobry przykład. –
http://david.tribble.com/text/cdiffs.htm - wiele z nich nadal obowiązuje w C++ 11. @CodyGray: VLA nie są częścią C++ 11. – Mat
@CodyGray: C++ 11 nie obsługuje VLA, więc twój komentarz może być odpowiedzią :) –