Câu trả lời:
Nếu bạn so sánh C89
vớiC++
thì đây là một vài điều
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 thêm rất nhiều trường hợp khác
// 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);
typedef;
là một TU hợp pháp trong C, nhưng không có trong C ++.
auto a;
hợp lệ trong bản sửa đổi tiêu chuẩn C ++ mới nhất.
a
gì?
auto x;
không hợp lệ trong phiên bản mới nhất, nhưng ví dụ auto x = 0;
là. Lúc đầu tôi đã hơi sốc :)
C ++ cũng có từ khóa mới. Sau đây là mã C hợp lệ nhưng sẽ không được biên dịch theo C ++:
int class = 1;
int private = 2;
int public = 3;
int virtual = 4;
Có rất nhiều thứ. Chỉ là một ví dụ đơn giản (cần đủ để chứng minh C không phải là tập con đúng của C ++):
int* test = malloc(100 * sizeof(int));
nên biên dịch trong C nhưng không phải trong C ++.
int*
.
void *
, trong C có thể được gán cho bất kỳ loại con trỏ nào và C ++ không thể được gán cho bất kỳ loại con trỏ nào khác.
Trong C ++, nếu bạn khai báo a struct
,union
hoặc enum
, tên của nó là ngay lập tức truy cập mà không cần bất kỳ vòng loại:
struct foo { ... };
foo x; // declare variable
Trong C, điều này sẽ không hoạt động, vì các loại do đó được khai báo sống trong các không gian tên riêng biệt của chúng. Vì vậy, bạn phải viết:
struct foo { ... };
struct foo x; // declare variable
Lưu ý sự hiện diện của struct
có trên dòng thứ hai. Bạn phải làm tương tự cho union
và enum
(sử dụng các từ khóa tương ứng của họ) hoặc sử dụngtypedef
mẹo:
typedef struct { ... } foo;
foo x; // declare variable
Do đó, bạn có thể có một số loại khác nhau được đặt tên giống nhau trong C, vì bạn có thể định hướng:
struct foo { ... };
typedef enum { ... } foo;
struct foo x;
foo y;
Tuy nhiên, trong C ++, mặc dù bạn có thể đặt tiền tố một struct
tên với từ khóa struct
bất cứ khi nào bạn tham chiếu nó, các không gian tên được hợp nhất và do đó đoạn mã C ở trên không hợp lệ. Mặt khác, C ++ đặc biệt tạo một ngoại lệ để cho phép một loại và một typedef cho loại đó có cùng tên (rõ ràng là không có tác dụng), để cho phép sử dụng typedef
thủ thuật không thay đổi từ C.
struct
, union
và enum
) chia sẻ cùng không gian tên. Một ví dụ tốt hơn sẽ làstruct foo { ... }; typedef enum { ... } foo;
Điều này cũng phụ thuộc vào loại C bạn đang sử dụng. Stroustrup làm cho C ++ tương thích nhất có thể, và không tương thích hơn, với các tiêu chuẩn ISO ANSI và 1990, và phiên bản 1995 không thay đổi gì. Ủy ban C đã đi theo một hướng khác với tiêu chuẩn năm 1999 và ủy ban C ++ đã thay đổi tiêu chuẩn C ++ tiếp theo (có thể ra vào năm tới hoặc lâu hơn) để phù hợp với một số thay đổi.
Stroustrup liệt kê sự không tương thích với C90 / C95 trong Phụ lục B.2 của "Ngôn ngữ lập trình C ++", Phiên bản đặc biệt (là phiên bản thứ 3 với một số tài liệu được thêm vào):
'a'
là một int
trong C, mộtchar
trong C ++.
Kích thước của một enum là int
bằng C, không nhất thiết phải bằng C ++.
C ++ có //
bình luận đến cuối dòng, C không (mặc dù đó là một phần mở rộng phổ biến).
Trong C ++, một struct foo {
định nghĩa đặt foo
vào không gian tên toàn cục, trong khi trong C, nó sẽ phải được gọi là struct foo
. Điều này cho phép một struct
định nghĩa che mờ một tên trong phạm vi bên ngoài và có một vài hậu quả khác. Ngoài ra, C cho phép phạm vi lớn hơn chostruct
định nghĩa và cho phép chúng trong khai báo kiểu trả về và kiểu đối số.
C ++ là khó khăn hơn về các loại nói chung. Nó sẽ không cho phép một số nguyên được gán cho một enum
và void *
các đối tượng không thể được gán cho các loại con trỏ khác mà không cần truyền. Trong C, có thể cung cấp trình khởi tạo chồng chéo (char name[5] = "David"
trong đó C sẽ loại bỏ ký tự null).
C89 cho phép ẩn int
trong nhiều ngữ cảnh và C ++ thì không. Điều này có nghĩa là tất cả các hàm phải được khai báo trong C ++, trong khi ở C89, người ta thường có thể nhận được bằng cách giả sử int
mọi thứ áp dụng trong khai báo hàm.
Trong C, có thể nhảy từ bên ngoài một khối vào bên trong bằng cách sử dụng câu lệnh được gắn nhãn. Trong C ++, điều này không được phép nếu nó bỏ qua một khởi tạo.
C tự do hơn trong liên kết bên ngoài. Trong C, một const
biến toàn cục là ngầm định extern
và điều đó không đúng trong C ++. C cho phép một đối tượng dữ liệu toàn cầu được khai báo nhiều lần mà không cầnextern
, nhưng điều đó không đúng trong C ++.
Nhiều từ khóa C ++ không phải là từ khóa trong C hoặc #define
d trong tiêu đề C tiêu chuẩn.
Ngoài ra còn có một số tính năng cũ của C không còn được coi là phong cách tốt nữa. Trong C, bạn có thể khai báo một hàm với các định nghĩa đối số sau danh sách các đối số. Trong C, một tuyên bố nhưint foo()
có nghĩa là foo()
có thể lấy bất kỳ số lượng bất kỳ loại đối số nào, trong khi trong C ++, nó tương đương với int foo(void)
.
Điều đó dường như bao gồm tất cả mọi thứ từ Stroustrup.
Nếu bạn sử dụng gcc, bạn có thể sử dụng cảnh báo -Wc++-compat
để đưa ra cảnh báo về mã C không rõ ràng trong C ++ theo một cách nào đó. Hiện tại nó được sử dụng trong gcc và gần đây nó đã tốt hơn rất nhiều (có thể thử phiên bản hàng đêm để có được thứ tốt nhất có thể).
(Điều này không trả lời đúng câu hỏi, nhưng dân gian có thể thích nó).
Sự khác biệt lớn nhất tôi nghĩ là đây là một tệp nguồn C hợp lệ:
int main()
{
foo();
}
Lưu ý rằng tôi chưa khai báo foo
bất cứ nơi nào.
Bên cạnh sự khác biệt về ngôn ngữ, C ++ cũng thực hiện một số thay đổi đối với thư viện mà nó được thừa hưởng từ C, ví dụ như một số hàm trả về const char *
thay vì char *
.
s,C,C89,
và lưu ý rằng đó là một tệp nguồn C99 không hợp lệ.
#include <stdio.h>
int new (int n) {
return n/2;
}
int main(void) {
printf("%d\n", new(10));
return 0;
}
Xem thêm mục C ++ FAQ .
Một số câu trả lời ở đây bao gồm các khác biệt về cú pháp sẽ khiến trình biên dịch C ++ không thành công trên mã nguồn C89 (hoặc C99). Tuy nhiên, có một số khác biệt ngôn ngữ tinh tế là hợp pháp trong cả hai ngôn ngữ nhưng điều đó sẽ tạo ra hành vi khác nhau. Sự sizeof (char)
khác biệt mà Naveen đã đề cập là một ví dụ, nhưng Viết chương trình sẽ in "C" nếu được biên dịch thành chương trình (ANSI) C và "C ++" nếu được biên dịch thành chương trình C ++ liệt kê một số chương trình khác.
Trình biên dịch C thường cho phép cắt một góc nhỏ mà C ++ không có. C ++ nghiêm ngặt hơn nhiều so với C. Và nói chung, một số khác biệt này phụ thuộc vào trình biên dịch. g ++ cho phép một số thứ mà trình biên dịch Intel C ++ không có, chẳng hạn. Ngay cả mã C được viết khá tốt cũng sẽ không được biên dịch với trình biên dịch C ++ hiện đại.
Bạn không thể so sánh các ngôn ngữ chỉ theo cú pháp. Nếu bạn làm điều đó có lẽ bạn có thể thấy C là tập con của C ++. Theo tôi, thực tế rằng C ++ là OO (và C không) là đủ để nói rằng C và C ++ là các ngôn ngữ khác nhau.