Я читал во многих книгах, что C - подмножество С++.
В некоторых книгах говорится, что C является подмножеством С++, за исключением небольших деталей.
Каковы некоторые случаи, когда код будет скомпилирован в C, но не С++?
Я читал во многих книгах, что C - подмножество С++.
В некоторых книгах говорится, что C является подмножеством С++, за исключением небольших деталей.
Каковы некоторые случаи, когда код будет скомпилирован в C, но не С++?
Если вы сравниваете C89
с C++
, то вот несколько вещей
int n;
int n; // ill-formed: n already defined
int a[1];
int (*ap)[] = &a; // ill-formed: a does not have type int[]
int b(a) int a; { } // ill-formed: grammar error
struct A { struct B { int a; } b; int c; };
struct B b; // ill-formed: b has incomplete type (*not* A::B)
auto a; // ill-formed: type-specifier missing
C99 добавляет много других случаев
// ill-formed: invalid syntax
void f(int p[static 100]) { }
// ill-formed: n is not a constant expression
int n = 1;
int an[n];
// ill-formed: fam has incomplete type
struct A { int a; int fam[]; };
// ill-formed: two names for one parameter?
void copy(int *restrict src, int *restrict dst);
В C, sizeof('a')
равно sizeof(int)
.
В С++ sizeof('a')
равен sizeof(char)
.
У С++ есть и новые ключевые слова. Ниже приведен допустимый код C, но он не будет скомпилирован под С++:
int class = 1;
int private = 2;
int public = 3;
int virtual = 4;
Есть много вещей. Просто простой пример (этого должно быть достаточно, чтобы доказать, что C не является надлежащим подмножеством С++):
int* test = malloc(100 * sizeof(int));
должен компилироваться в C, но не в С++.
В С++, если вы объявляете struct
, union
или enum
, его имя сразу же доступно без каких-либо квалификаторов:
struct foo { ... };
foo x; // declare variable
В C это не будет работать, потому что типы, объявленные таким образом, живут в своих собственных пространствах имен. Таким образом, вы должны написать:
struct foo { ... };
struct foo x; // declare variable
Обратите внимание на наличие struct
на второй строке. Вы должны сделать то же самое для union
и enum
(используя их соответствующие ключевые слова) или использовать трюк typedef
:
typedef struct { ... } foo;
foo x; // declare variable
Следовательно, вы можете иметь несколько типов разных типов, названных одинаковыми в C, поскольку вы можете устранить неоднозначность:
struct foo { ... };
typedef enum { ... } foo;
struct foo x;
foo y;
В С++, хотя вы можете префикс имени struct
с ключевым словом struct
всякий раз, когда вы ссылаетесь на него, пространства имен объединяются, и поэтому приведенный выше фрагмент кода C недействителен. С другой стороны, С++ специально создает исключение, чтобы тип и typedef для этого типа имели одно и то же имя (очевидно, без эффекта), чтобы использовать трюк typedef
без изменений от C.
Это также зависит от того, какое разнообразие C вы используете. Stroustrup сделал С++ настолько совместимым, насколько он мог, и не более совместим с 1989 стандартами ANSI и 1990 ISO, а версия 1995 года ничего не изменила. Комитет С пошел в несколько другом направлении со стандартом 1999 года, и комитет С++ изменил следующий стандарт С++ (возможно, в следующем году или около того), чтобы соответствовать некоторым изменениям.
Stroustrup перечисляет несовместимости с C90/C95 в Приложении B.2 "Язык программирования С++", Special Edition (который является третьим изданием с некоторыми дополнительными материалами):
'a'
является int
в C, a char
в С++.
Размер перечисления int
в C, не обязательно в С++.
С++ имеет //
комментарии к концу строки, C не является (хотя и является общим расширением).
В С++ определение struct foo {
помещает foo
в глобальное пространство имен, тогда как в C оно должно называться struct foo
. Это позволяет определить struct
тень имени во внешней области и имеет несколько других последствий. Кроме того, C позволяет расширить область определения struct
и позволяет им в объявлениях типа возвращаемого типа и типа аргументов.
С++ более суетливо относится к типам вообще. Он не позволит назначать целое число для объектов enum
, а void *
нельзя назначать другим типам указателей без трансляции. В C можно предоставить перекрывающий инициализатор (char name[5] = "David"
, где C отбрасывает конечный нулевой символ).
C89 допускает неявный int
во многих контекстах, а С++ - нет. Это означает, что все функции должны быть объявлены в С++, в то время как в C89 часто можно было обойтись с предположением int
для всего, что применимо в объявлении функции.
В C можно перепрыгнуть извне блок внутрь, используя обозначенный оператор. В С++ это недопустимо, если оно пропускает инициализацию.
C более либеральна во внешней связи. В C глобальная переменная const
неявно extern
, и это не верно в С++. C позволяет объявлять глобальный объект данных несколько раз без extern
, но это не так на С++.
Многие ключевые слова С++ не являются ключевыми словами в C или являются #define
d в стандартных заголовках C.
Есть также некоторые более старые функции C, которые больше не считаются хорошим стилем. В C вы можете объявить функцию с определениями аргументов после списка аргументов. В C объявление типа int foo()
означает, что foo()
может принимать любое количество аргументов любого типа, тогда как в С++ оно эквивалентно int foo(void)
.
Это похоже на все, что от Страустрапа.
#include <stdio.h>
int new (int n) {
return n/2;
}
int main(void) {
printf("%d\n", new(10));
return 0;
}
См. также запись в С++ FAQ.
Единственное самое большое различие, которое я думаю, это то, что это действительный исходный файл C:
int main()
{
foo();
}
Обратите внимание, что я нигде не объявлял foo
.
Помимо языковых различий, С++ также вносит некоторые изменения в библиотеку, которую он унаследовал от C, например. некоторые функции возвращают const char *
вместо char *
.
Если вы используете gcc, вы можете использовать предупреждение -Wc++-compat
, чтобы дать вам предупреждения о C-коде, который так или иначе сомневается в С++. В настоящее время он используется в самой gcc, и в последнее время он стал намного лучше (возможно, попробуйте ночную версию, чтобы получить все возможное).
(Это не дает строгого ответа на вопрос, но людям это может понравиться).
В нескольких ответах здесь рассматриваются различия синтаксиса, которые могут привести к сбою компиляторов С++ в исходном коде C89 (или C99). Однако существуют некоторые тонкие языковые различия, которые являются законными на обоих языках, но это может привести к поведению. Разница sizeof (char)
, упомянутая Навееном, является одним из примеров, но Напишите программу, которая будет печатать "C" если он скомпилирован как программа (ANSI) C и "С++" если он скомпилирован как программа на С++, перечислены некоторые другие.
C обычно разрешали небольшую угловую резку, которой нет на С++. С++ гораздо более строг, чем C. И, как правило, некоторые из этих различий зависят от компилятора. g++ позволяет, например, некоторые вещи, которые компилятор Intel С++ не делает. Даже довольно хорошо написанный код C не будет компилироваться с помощью современного компилятора С++.
Вы не можете сравнивать языки только по синтаксису. Если вы это сделаете, возможно, вы можете увидеть C как подмножество С++. На мой взгляд, того факта, что С++ является OO (и C не является), достаточно, чтобы сказать, что C и С++ - разные языки.