Различия
1) Объявления функций в старом стиле С не разрешено в С++
double alt_style( a , real ) /* Obsolete function definition */ double *real; int a; { return ( *real + a ) ; }
2) Программы на С не должны использовать имена, которые являются ключевыми словами в С++ если хочется совместить портируемость
3) Комментарии в стиле С++ (//) появились только в C99
4) В С++ есть новые операции .*, ->*, :: которых нет в C
5) sizeof(‘a’) == sizeof(char) // C++
sizoef(‘a’) == sizeof(int) // C
Достаточно много важной информации содержится в "C++2003 5.3.3 Sizeof" в то числе сказано, что:
- sizeof(char) со всеми вариациями char-а это всегда один байт
- sizeof(bool), sizeof(wchar_t) это implementation-defined
6) C++ 1998 использует препроцессор С89, хотя язык С претерпел изменения: Tradition C, C89, C95, C99, C11
7) Теги структур в С++ включаются в пространство имен “другие имена”.
В этом пространстве находятся
-- переменные
-- функции
-- typedef имена
-- константы перечисления
Поэтому struct n{}; typedef double n;// корректно в С, но не в С++
Однако, хотя для С++ имена тегов типов (struct, union, enum) неявно объявляются с
помощью typedef, но всё же они могут спрятаны переменными в той же области видимости “S S;”
8) В С89 разрешены квалификаторы типа const, volatile. В C99 добавился restrict, которого нет в C++
9) Массивы с переменной длинной
varying array. В C99 последний член структуры может быть гибким массивом.
В С++ также.
flexible arrays. В С99, но не в C++ разрешаются массивы с размером заданным не через константную переменную. В С99 для передачи таких аргументов в функцию следует использовать нотацию void g(int pp[*], int k){}
10) Различная инициализация массива char. В С++ массив должен иметь достаточный размер для хранения "\0" символа
char a[3]="12"; char aEquiv[]="12";// нормально в С/С++
char a[3]="123"; // нормально в С, но не в С++
11) В C99 есть именованные инициализаторы для структур, и позиционные инициализаторы для массивов, в C++ нет.
12) Определение struct и union в C++ имеют блочную область видимость
13) Объявления const имеют по умолчанию static в с++ ,
но extern в С (Appendix C. C++2003)
7.11.6, C++2003:
"A name declared in a namespace scope without a storage-class-specifier has external linkage unless it has internal linkage because of a previous declaration and provided it is not declared const. Objects declared const and not explicitly declared extern have internal linkage."
Из этого абзаца так же следует, что объявления не const переменных, объявленные на
уровне пространства имён имеют по умолчанию extern linkage в C++
15) Объявление С++ void f() эквивалентно void f(void) в С.
Объявление в С void f() говорит о функции с неопределенным кол-ом аргументов.
16) Если массив многомерный то во всех вариантах может быть опущен только самый левый индекс, для наличия возможности определения размера массива. Так же в С99 разрешена покомпонентная инициализация.
17) При использовании union для смеси струтктур начинающихся одинаково есть
гарантия идентичного мапинья компонент "из этого начала"
18) В С, но не в C++ можно написать хотя это и странно: sizeof(struct S{int a;});
19) Неявное приведение из целого типа в enum разрешено в C, но не в C++
С++ 2003-10-15. page 113. 7.2.5: Тип enum-а - целочисленный тип, который должен поддерживать все underlying значения. В С enum есть синоним int.
20) В С++, преобразование указателя типа void в любой ссылочный тип требует явной операции приведения, в С это выполняется неявно.
21) Безусловный переход через goto разрешен в середину вложенного блока в С (при этом инициализация автоматических переменных не гарантируется), это не разрешено в С++. Исключение - POD типы. Однако никаких гарантий на инициализацию нет.
21) В С++ функцию main нельзя вызвать рекурсивно
22) В С++ более жесткие требования к inline функциям - встраиваемая функция должна быть объявлена такой во всех исходных файлах, в C99 это не так.
В С++ inline функция с точки зрения кода может иметь адрес и статические переменные внутри.
В C99 компилятор должен видеть определение функции, т.е. функцию определять чтобы она заинлайнилась надо в *.h. Компилятор может выбрать как и правда inline-ить вызовы, так и не инлайнить, так и инлайнить частично.
23) В C++ разрешено объявление в условиях
24) В C нет такого типа как ссылка.
Про ссылки рассказано в "С++2003, 8.3.2. References". Например: A reference shall be initialized to refer to a valid object or function. [Note: in particular, a null reference cannot exist in a well-defined program...]
25) В С нет перегруженных функций
26) В С++ есть параметры по умолчанию
27) Механизм пространства имён которые namespace
28) C использованием exit() и abort() приходит проблема с тем, что деструкторы локальных объектов не вызываются
29) перегрузка операторов, функций разрешена только в C++
30) C не поддерживает General-Purpose-Programming,
в С++ поддержка на уровне шаблонов
31) В языке С компонентам структур даются адреса. Есть гарантия того, что адреса компонент находятся в возрастающем порядке. И адрес первого компонента совпадает с адресом начала структуры. Вне зависимости какой endian у компьютера где будет запускаться программа.
32) sizeof структуры в С равен объему памяти для хранения всех компонент, место под padding между компонентами, место под padding после структур. Для структур и для других типов должно выполняться правило - размер массива из N элементов в байтах, равен N умножить на размер элемента массива
33) В С и C++ допустимы для реализации три вида представления целых чисел со знаком из n бит:
дополнение до двух (twos-complement-notation) [-2**(n-1), +2**(n-1)-1].
положительные числа представлены обычным образом, самый старший бит знака установлен в 0
отрицательные числа получаются как (инвертировать биты(число)+1) в нотации команд ASM для x86 звучит как операция NEG
1000000..000 - максимальное отрицательное число, которое не имеет положительного эквивалента.
дополнение до одного (ones-complement-notation) [-2**(n-1)+1, +2**(n-1)-1]
отрицательные числа есть дополнение всех бит соответственного положительного числа. В данном представлении возможны положительный и отрицательный ноль
Знаковое представление целого числа (sign-magnitude-notation) [-2**(n-1)+1, +2**(n-1)-1]
Представление модуля отрицательных и положительных чисел идентично. В старшем бите хранится знак числа.
34) Если функция принимает переменное кол-во аргументов "..." значения, то для них происходят обычные унарные преобразования с повышением типа. И кроме того float повышается до double.
35) В C++ для определяющего определения переменной extern int a = 0; extern игнорируется
36) Нуль указатель в C|C++ - любое целочисленное выражение дающее ноль. Или такое выражение скастованное в указатель.
Выражения ниже не приведут к ошибки компиляции как бы этого не хотелось бы:
void y(int*){}
y(0);
37) В C99 есть предопределенный идентификатор (predefined identifier) __func__
Этот идентификатор неявно определяется компилятором в начале тела функции как static const char __func__[] = "function-name"
38) Про макрорасширения препроцессора в C/C++.
Как только макровызов заменяется расширением, процесс поиска макровызовов начинается с начала развернувшегося расширения для дальнейшей замены. Во время этого процесса для макросов которые упоминаются в собственном расширении повторное расширение не происходит.
#define sqrt(x) (x<0 ? sqrt(x) : sqrt(-x))
39) Использование компилятором unsigned или signed в случае отсутстивя явного указания типа не определено для char-а. Такая же ситуация с битовыми полями.
40) Для структур не разрешено выполнять сравнения на ==, >. Фундаментальность этого ограничения в C связана с тем, что
для объектов могут быть дырки в их layout по памяти.
41) Вообще говоря результат выполнение свдига вправо для целых типов со знаком в случае отрицательных чисел не определён.
Реализатор компилятора может выполнить как логический сдвиг вправо, так и арифметический. (Харбисон, Стил, Язык программирования C, стр. 252)
42) Базовые вещи про кодогенерацию различных конструкторов http://www.cplusplus.com/articles/y8hv0pDG/ и всяких operator=
Дополнительные замечания
A (*B) - что это? Объявление переменной или вызов функции. Эта неоднозначность делает грамматику С Контекстно Зависимой, а не LALR(1)
С/С++ постфиксные операции имеют более высокий приоритет чем унарные операции, которые в свою очередь имеют более высокий приоритет чем бинарные операции. "==", "!=" имеют более высокий приоритет чем логические связки.
В С++ фишечные операторы С++ обычно имеют самый высокий приоритет, кроме throw - который выше только оператора запятая.
В С++ и в С порядок вычисления подвыражений не определён A(F(), G()). Более того компилятору разрешено в произвольном порядке вычислять операнды бинарной операции, а также выполнять оптимизации в зависимости от ассоциативности и коммутативности операции.
В C++ контроль на уровень доступа позже, чем на неоднозначность.
Ошибка компиляции
class A {
public:
int a;
private:
int a;
};
Контроль на перегрузку после контроля на неоднозначность.
36) К параметрам шаблона кроме типа относятся так же Non Type Parametrs, которые могут иметь тип интегральной константы, ссылки, и указателя на данное или функцию. Указатели на данное должны иметь внешний тип линковки.
37) Статические переменные инициализируются нулём для соответствующего типа. Переменные типа массив и структура инициализируются нулём при пустом списке инициализации.
38) В языке С в списке инициализации должен присутствовать по крайней мере один элемент при инициализации структуры или массива. В случае если для массива или структуры количество инициализирующих значений меньше размерности массива или структуры - остаток элементов инициализируются значением по умолчанию для соответствующего типа (как и в случае инициализации статических переменных) См. Виды инициализации в C++
http://stackoverflow.com/questions/8256293/default-initialization-of-pod-vs-non-pod-class-types
"The class you show is a POD, so ... your object will not be initialized at all "
поподробнее про инициализацию: 8.5, 8.5.1 Initializers from C++2003-10-15
39) Объединение не может иметь в качестве члена объект с определенным пользователем конструктором.
40) При использовании преобразований пользователя (конструкторы/преобразования типов) допустим только один уровень неявных используемых преобразований
41) В C/C++ выражение указатель на функцию может быть использовано для вызова функции без явного разыменования указателя, т.е. можно вызвать функцию как (*f)() так и f()
Фундаментальные типы гарантий C++ кода:
Basic Garantee - нет утечек и стандартные библиотеки поддерживаются
Strong Garantee - или операция полностью выполняется или нет
Все контейнеры в c++98 дают basic garantee. А некоторые операции (например std::vector<T>::push_back) дают strong garantee
Что такое C++ с точки зрения Б. Страуструпа
Бьерн Страуструп (2010 г.) шуточно описывает С++ как язык:
1) Support generic programming
2) Hybrid language
3) Multi-paradigm programming Language
4) Buffer Overflows
5) Too Big
6) Object-Oriented-Programming Language
7) Low Level
8) Embedded system language
9) Random Collections of features
10) It’s C!