C (99)와 C ++ (11)의 비 호환 차이점은 무엇입니까?
이 질문은 Herb Sutter 의 게시물에 대한 답변으로 촉발되었으며 , C99 컴파일러를 지원 / 만들지 않고 어쨌든 C ++ (11) 표준에있는 C (99) 기능을 사용하기로 한 MS의 결정을 설명했습니다.
(...) C는 중요하며 적어도 약간의주의를 기울여야합니다.
유효한 C이지만 유효한 C ++가 아닌 기존 코드가 많이 있습니다. 해당 코드는 다시 작성되지 않을 것입니다. (...)
나는 MS C ++로만 프로그래밍하기 때문에 "순수한"C를 잘 모릅니다. 즉, 사용중인 C ++ 언어의 세부 사항이 C (99)에 없는지 알 수 없습니다. 일부 C99 코드가 C ++ 컴파일러에서있는 그대로 작동하지 않는 단서.
restrict
나에게 매우 좁은 응용 프로그램을 가지고있는 것처럼 보이는 C99 유일한 키워드 와 가변 길이 배열에 대해 알고 있다는 점에 유의하십시오 (이 키워드가 얼마나 널리 퍼져 있는지 또는 중요한지 잘 모르겠습니다).
또한 C ++ (11)에서 컴파일 되지만 C 컴파일러와 C ++ 컴파일러에서 다른 작업을 수행 하는 C (99) 코드와 같은 중요한 의미 적 차이나 문제가 있는지 여부에 매우 관심이 있습니다 .
빠른 링크 : 답변의 외부 리소스 :
- Wikipedia 페이지
- David R. Tribble의 비교 (2001 년부터)
- C ++ 11 표준 : http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3376.pdf (섹션 C.1)
C와 C ++의 공통 부분 집합에서 시작하는 경우 (C90이 아닌 클린 C라고도 함) 다음 세 가지 유형의 비 호환성을 고려해야합니다.
합법적 인 C를 불법적 인 C ++로 만드는 추가 C ++ 기능
이에 대한 예는 C에서 식별자로 사용할 수있는 C ++ 키워드 또는 C에서 암시 적이지만 C ++에서 명시 적 캐스트가 필요한 변환입니다.
이것이 마이크로 소프트가 여전히 C 프런트 엔드를 제공하는 주된 이유 일 것입니다. 그렇지 않으면 C ++로 컴파일되지 않는 레거시 코드를 다시 작성해야합니다.
C ++의 일부가 아닌 추가 C 기능
C ++가 분기 된 후에도 C 언어는 진화를 멈추지 않았습니다. 가변 길이 배열, 지정된 이니셜 라이저 및
restrict
. 이러한 기능은 매우 편리 할 수 있지만 C ++ 표준의 일부가 아니며 일부 기능은 결코 사용할 수 없습니다.C와 C ++ 모두에서 사용할 수 있지만 의미가 다른 기능
이에 대한 예는
const
객체 또는inline
함수 의 연결입니다 .
C99와 C ++ 98 사이의 비 호환성 목록은 여기에서 찾을 수 있습니다 (이미 Mat에서 언급했습니다).
C ++ 11과 C11이 일부면에서 가까워졌지만 (가변 매크로는 이제 C ++에서 사용 가능하고 가변 길이 배열은 이제 선택적 C 언어 기능 임) 비 호환성 목록도 증가했습니다 (예 : C 및 auto
C ++의 유형 지정자).
제쳐두고, 마이크로 소프트는 C (최근이 아님)를 포기하기로 결정하는데 열을가했지만, 오픈 소스 커뮤니티의 아무도 실제로 그것에 대해 조치를 취하지 않았다는 것을 알고 있습니다. C-to-C ++ 컴파일러를 통해 최신 C의 많은 기능을 제공 할 수 있습니다. 특히 일부 기능이 . 이것은 실제로 지금 C99를 지원하는 Comeau C / C ++를 사용하여 가능합니다.
그러나 이것은 실제로 시급한 문제는 아닙니다. 개인적으로 저는 Windows에서 GCC와 Clang을 사용하는 것이 매우 편안하며 MSVC에 대한 독점적 인 대안도 있습니다 (예 : Pelles C 또는 Intel의 컴파일러).
C99 및 C11에는 몇 년 동안 (C90 또는 그 이전)에 있었던 많은 비 호환성과 정말 멋진 기능이 많이 있습니다. 이것들은 모두 내 머리 꼭대기에서 벗어났습니다.
// 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는 훌륭하고 어디에서나 C 프로그래머가 사용해야합니다.
C99의 새로운 기능은 일반 프로그래밍에 매우 좋습니다. VLA restrict
는 (내 의견으로는) 일반적인 사용을 대상으로하지 않지만 대부분 FORTRAN 및 숫자 프로그래머를 C로 가져 오는 restrict
데 사용됩니다 (자동 벡터화를 돕지 만). 를 사용하는 모든 준수 프로그램 은 파일 맨 위에있는 restrict
경우에도 똑같은 방식으로 작동하지만 빠르지 #define restrict
않을 수 있으므로 큰 문제는 아닙니다. VLA는 야생에서 매우 드뭅니다.
유연한 배열 구성원이 좋을 수 있습니다. 이들은 가변 길이 배열과 동일하지 않습니다! 사람들은이 트릭을 수년 동안 사용해 왔지만 공식적인 지원은 타이핑이 적다는 것을 의미하며 컴파일 타임에 상수를 만들 수도 있습니다. (이전 방법은 크기가 1 인 배열을 사용하는 것이었지만 할당 크기를 계산하는 것은 정말 귀찮습니다.)
struct lenstr {
unsigned length;
char data[];
};
// compile time constant
const struct lenstr hello = { 12, "hello, world" };
지정된 이니셜 라이저. 많은 타이핑을 절약합니다.
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
키워드 동작합니다 다르게, 당신은 함수의 인라인이 아닌 버전은 그 기기에 통근 선언을 추가하여 인라인 선언 얻을 수있는 변환 장치를 선택할 수 있습니다.
복합 리터럴.
struct point { float x; float y; };
struct point xy_from_polar(float r, float angle)
{
return (struct point) { cosf(angle) * r, sinf(angle) * r };
}
The (snprintf
function is probably in my top 10 most useful library functions in C. It's not only missing from C++, but the MSVC runtime only provides a function called _snprintf
, which is not guaranteed to add a NUL terminator to the string.snprintf
is in C++11, but still conspicuously absent from the MSVC C runtime.)
Anonymous structures and unions (C11, but GCC extension since forever) (anonymous unions are apparently in C++03, no MSVC support in C mode):
struct my_value {
int type;
union {
int as_int;
double as_double;
}; // no field name!
};
As you can see, many of these features just save you a lot of typing (compound literals), or make programs easier to debug (flexible array members), make it easier to avoid mistakes (designated initializers / forgetting to initialize structure fields). These aren't drastic changes.
For semantic differences, I'm sure the aliasing rules are different, but most compilers are forgiving enough these days I'm not sure how you'd construct a test case to demonstrate. The difference between C and C++ that everyone reaches for is the old sizeof('a')
expression, which is always 1 for C++ but usually 4 on a 32-bit C system. But nobody cares what sizeof('a')
is anyway. However, there are some guarantees in the C99 standard that codify existing practices.
Take the following code. It uses a common trick for defining union types in C without wasting extra storage. I think this is semantically valid C99 and I think this is semantically dubious C++, but I might be wrong.
#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);
}
}
It's a shame, though. The MSVC code generator is nice, too bad there's no C99 front-end.
In C++, setting one member of a union and accessing the value of a different member is undefined behavior, whereas it's not undefined in C99.
There are lots of other differences listed on the wikipedia page.
I will mention "C.1 C++ and ISO C" of the C++11 standard. That document has a blow by blow of each difference and its impact on development.
ReferenceURL : https://stackoverflow.com/questions/10461331/what-are-the-incompatible-differences-between-c99-and-c11
'programing' 카테고리의 다른 글
PDF 문서에서 텍스트를 추출하는 방법은 무엇입니까? (0) | 2021.01.15 |
---|---|
C #에서 문자열의 개별 문자를 반복하는 가장 빠른 방법은 무엇입니까? (0) | 2021.01.15 |
Callable과 유사한 인터페이스가 있지만 인수가 있습니까? (0) | 2021.01.15 |
JavaFX 2.1 : 툴킷이 초기화되지 않았습니다. (0) | 2021.01.15 |
두 C # 개체 간의 속성 차이 찾기 (0) | 2021.01.15 |