C가 C ++의 하위 집합이 아닌 곳은 어디입니까? [닫은]


116

C가 C ++의 하위 집합이라는 책을 많이 읽었습니다.

일부 책 에서는 작은 세부 사항을 제외하고 C가 C ++의 하위 집합이라고 말합니다 .

코드가 C로 컴파일되지만 C ++에서는 컴파일되지 않는 경우에는 어떤 것이 있습니까?

답변:


135

당신이 비교하는 경우 C89C++여기에 몇 가지 있습니다

C ++에 임시 정의가 없습니다.

int n;
int n; // ill-formed: n already defined

int [] 및 int [N]이 호환되지 않음 (C ++에서 호환 가능한 유형 없음)

int a[1];
int (*ap)[] = &a; // ill-formed: a does not have type int[]

K & R 함수 정의 스타일 없음

int b(a) int a; { } // ill-formed: grammar error

중첩 구조체에는 C ++에서 클래스 범위가 있습니다.

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);

@mehrdad, 감사합니다. oO는 C에서 중첩 된 구조체를 선언 할 때 이미 변수를 만들어야한다는 것을 몰랐습니다. 고정.
Johannes Schaub-litb 2007 년

3
또 다른 (쓸모없는) C89 to C ++ 하나가 있습니다. typedef;C에서는 합법적 인 TU이지만 C ++에서는 아닙니다.
Flexo

공지 사항 auto a;최신 C ++ 표준 개정에 유효합니다.
fuz

3
@FUZxxl 정말? 추론 된 유형은 a무엇입니까?
Johannes Schaub-litb

3
@FUZxxl 아 감사합니다. 따라서 auto x;최신 개정판에서는 유효하지 않지만 예를 들어 auto x = 0;그렇습니다. 나는 처음에 약간 충격을 받았다 :)
Johannes Schaub-litb

50

C에서 sizeof('a')와 동일하다 sizeof(int).

C ++에서, sizeof('a')동일하다 sizeof(char).


46
simpified로 될 수 있음 : C에서, 'a'이다 int. C ++에서 'a'A는 char.
pmg

38

C ++에도 새로운 키워드가 있습니다. 다음은 유효한 C 코드이지만 C ++에서 컴파일되지 않습니다.

int class = 1;
int private = 2;
int public = 3;
int virtual = 4;

1
사실이지만 이것이 바로 서브 세트가 의미하는 바입니다.
yeyeyerman

20
@yeyeyerman : 아니요. 하위 집합이 되려면 모든 C 코드도 유효한 C ++ 여야합니다. 이 예제의 코드는 유효한 C이지만 C ++는 아닙니다.
jalf

24
아니요, C가 C ++의 엄격한 하위 집합이면 모든 C 프로그램은 유효한 C ++ 프로그램이 될 수 있지만 사실이 아닙니다. 문제는 그것이 사실이 아닌 이유이며, 이것이 그 이유의 한 예입니다.
Graeme Perrow

하아! 이것에 대해 생각하지 않았습니다!
Gab Royer

20

많은 것들이 있습니다. 간단한 예입니다 (C가 C ++의 적절한 하위 집합이 아님을 증명하기에 충분해야합니다).

int* test = malloc(100 * sizeof(int));

C로 컴파일해야하지만 C ++에서는 컴파일하지 않아야합니다.


3
C ++는 int*.
메흐 다드 Afshari

8
긴 대답 : malloc은 void *C에서 어떤 포인터 유형에도 할당 할 수 있는를 반환 하고 C ++는 다른 포인터 유형에 할당 할 수 없습니다.
Daniel Earwicker

5
Imagist : ANSI C89 표준에 정의 된 C 컴파일러는 불평하지 않아야합니다.
Mehrdad Afshari

7
그것은 합법적 인 C입니다. 캐스트는 불필요하고 잘못 될 가능성이 있으며 <stdlib.h>를 포함하지 않은 것을 은폐합니다. 나는 다드의 문이 C에서 그것을 쓸 수있는 올바른 방법이라고 생각
데이빗 쏜리

16
@Imagist : 저는 보통 C 프로그래머의 반대 말을 듣습니다. 그들은 버그를 숨길 수 있기 때문에 캐스트를 추가하는 것이 좋지 않은 스타일이라고 생각합니다. 좋은 C 코드는 캐스트를 사용 하지 않습니다 .
jalf

16

당신이 선언하는 경우 C ++에서 struct, union또는 enum, 그 이름은 예선없이 바로 액세스 할 수 있습니다 :

struct foo { ... };
foo x; // declare variable

C에서는 이렇게 선언 된 유형이 고유 한 네임 스페이스에 있기 때문에 작동하지 않습니다. 따라서 다음과 같이 작성해야합니다.

struct foo { ... };
struct foo x; // declare variable

의 존재에 주목 struct번째 줄에 존재합니다. unionenum(각 키워드 사용)에 대해 동일한 작업을 수행 하거나 typedef트릭을 사용해야합니다 .

typedef struct { ... } foo;
foo x; // declare variable

결과적으로 C에서 동일한 이름을 가진 여러 유형의 다른 종류를 가질 수 있습니다.

struct foo { ... };
typedef enum { ... } foo;

struct foo x;
foo y;

그러나 C ++에서는 struct이름 struct을 참조 할 때마다 키워드 접두사를 붙일 수 있지만 네임 스페이스가 병합되므로 위의 C 스 니펫은 유효하지 않습니다. 반면에 C ++는 C typedef에서 변경되지 않은 트릭을 사용할 수 있도록 해당 유형에 대한 유형과 typedef가 동일한 이름 (분명히 효과 없음)을 가질 수 있도록 특별히 예외를 만듭니다 .


1
마지막 예는 잘못된 C입니다. 세 개의 태그 ( struct, unionenum)가 동일한 네임 스페이스를 공유합니다. 더 좋은 예는 다음과 같습니다struct foo { ... }; typedef enum { ... } foo;
schot

@schot : 물론 맞습니다. 수정 해 주셔서 감사합니다. 업데이트되었습니다.
Pavel Minaev

8

이것은 또한 사용중인 C의 종류에 따라 다릅니다. Stroustrup은 C ++를 1989 ANSI 및 1990 ISO 표준과 최대한 호환되도록 만들었으며 더 이상 호환되지 않게 만들었으며 1995 버전은 아무것도 변경하지 않았습니다. C위원회는 1999 년 표준과는 다소 다른 방향으로 갔고, C ++위원회는 일부 변경 사항에 맞추기 위해 다음 C ++ 표준 (아마 내년 정도)을 변경했습니다.

Stroustrup은 "The C ++ Programming Language", Special Edition의 부록 B.2 (일부 자료가 추가 된 3 판)에 C90 / C95와의 비 호환성을 나열합니다.

'a'입니다 intC에서, charC ++에서이.

열거 형의 크기는 intC로되어 있으며 반드시 C ++로되어 있지는 않습니다.

C ++에는 //줄 끝에 주석이 있지만 C 에는 주석이 없습니다 (일반적인 확장 임에도 불구하고).

C ++에서는 struct foo {정의가 foo전역 네임 스페이스에 배치되고 C에서는 struct foo. 이렇게하면 struct정의가 외부 범위의 이름을 숨기고 몇 가지 다른 결과가 발생합니다. 또한 C는 struct정의에 대해 더 큰 범위를 허용하고 반환 유형 및 인수 유형 선언에서 허용합니다.

C ++는 일반적으로 유형에 대해 까다 롭습니다. 그것은 정수가 할당되는 것을 허용하지 않습니다 enum, 그리고 void *개체를 캐스팅없이 다른 포인터 타입에 할당 할 수 없습니다. C에서는 너무 큰 이니셜 라이저를 제공 할 수 있습니다 ( char name[5] = "David"여기서 C는 후행 널 문자를 버립니다).

C89 int는 많은 컨텍스트에서 암시 적 으로 허용되었지만 C ++는 그렇지 않습니다. 즉, 모든 함수는 C ++로 선언해야하지만 C89 int에서는 함수 선언에 적용 할 수있는 모든 것을 가정하여 얻을 수있는 경우가 많습니다 .

C에서는 레이블이 지정된 명령문을 사용하여 블록 외부에서 내부로 이동할 수 있습니다. C ++에서는 초기화를 건너 뛰면 허용되지 않습니다.

C는 외부 연결에서 더 자유 롭습니다. C에서 전역 const변수는 암시 적 extern으로이며 C ++에서는 사실이 아닙니다. C를 사용하면 전역 데이터 개체를.없이 여러 번 선언 할 수 extern있지만 C ++에서는 그렇지 않습니다.

많은 C ++ 키워드는 C의 키워드가 아니거나 #define표준 C 헤더의 d입니다.

더 이상 좋은 스타일로 간주되지 않는 C의 오래된 기능도 있습니다. C에서는 인수 목록 뒤에 인수 정의가있는 함수를 선언 할 수 있습니다. C에서 다음과 같은 선언 은 임의의 수의 인수 유형을 취할 수 int foo()있음을 의미 foo()하지만 C ++에서는 int foo(void).

Stroustrup의 모든 것을 다루는 것 같습니다.


C에서는 스코프의 시작 부분 (즉, 여는 중괄호 바로 뒤)에 변수를 선언해야한다는 사실을 잊지 마십시오. 반면 C ++는 어디에서나 변수 선언을 허용합니다.
RobH

4
그러나 그것은 C ++가 할 수있는 일이고 C가 할 수없는 일입니다. 우리는 C에서 할 수 있지만 C ++에서는 할 수없는 일을보고 있다고 생각합니다.
David Thornley

2
@RobH : C89에서는 사실이지만 C99에서는 그렇지 않습니다.
jamesdlin

6

gcc를 사용하는 경우 경고 -Wc++-compat를 사용하여 어떤 식 으로든 C ++에서 모호한 C 코드에 대한 경고 를 제공 할 수 있습니다 . 현재 gcc 자체에서 사용되고 있으며 최근에는 훨씬 더 나아졌습니다 (아마도 최선을 다하기 위해 야간 버전을 사용해보십시오).

(이것은 질문에 엄격하게 대답하지는 않지만 사람들은 그것을 좋아할 것입니다).


1
나는 대답이없는 대답을 결코
찬성

4

내가 생각하는 가장 큰 차이점은 이것이 유효한 C 소스 파일이라는 것입니다.

int main()
{
    foo();
}

나는 foo어디에도 선언하지 않았습니다 .

언어 차이 외에도 C ++는 C에서 상속 된 라이브러리를 일부 변경합니다. 예를 들어 일부 함수 const char *char *.


맞습니다. C에서는 프로토 타입이 필요하지 않지만 일반적으로 사용하지 않는 것은 나쁜 습관으로 간주됩니다.
Robert Gamble

1
s,C,C89,파일은 유효하지 않은 C99 소스 파일입니다.
Johannes Schaub-litb

유효하지 않거나 C99에서 더 이상 사용되지 않습니까?
jalf

2
@jalf C99 초안은 C89의 변경 사항을 문서화하고 "remove implicit int"및 "remove implicit function declaration"을 모두 포함합니다.
Johannes Schaub-litb


2

여기에 나와있는 여러 답변은 C89 (또는 C99) 소스 코드에서 C ++ 컴파일러가 실패하는 구문 차이를 다룹니다. 그러나 두 언어 모두에서 합법적이지만 다른 동작을 생성하는 미묘한 언어 차이가 있습니다. sizeof (char)나빈이 언급 한 차이점은 하나의 예이지만, (ANSI) C 프로그램으로 컴파일 된 경우 "C"를 인쇄합니다 프로그램 및 "C ++"는 C ++ 프로그램으로 컴파일 된 경우 쓰기 목록 일부 다른 사람을.


-2

C 컴파일러는 일반적으로 C ++에서 허용하지 않는 약간의 코너 컷을 허용했습니다. C ++는 C보다 훨씬 엄격합니다. 일반적으로 이러한 차이점 중 일부는 컴파일러에 따라 다릅니다. g ++는 예를 들어 인텔 C ++ 컴파일러가 할 수없는 몇 가지를 허용합니다. 상당히 잘 작성된 C 코드조차도 최신 C ++ 컴파일러로 컴파일되지 않습니다.


-2

구문만으로 언어를 비교할 수 없습니다. 그렇게하면 C를 C ++의 하위 집합으로 볼 수 있습니다. 제 생각에는 C ++가 OO (그리고 C는 아닙니다)라는 사실은 C와 C ++가 다른 언어라고 말하기에 충분합니다.


2
잘못된. C ++는 단지 OO 가 아닙니다 . "C ++ = C + OO + 일반 프로그래밍 + 보너스"와 같은 C ++를 생각할 수 있습니다. 다시 말해, "C & C ++ ~ = C"여기서 ~ =는 거의 같음을 의미합니다.
paercebal
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.