Вопрос по c++, c++11, c – Каковы несовместимые различия между C (99) и C ++ (11)?

54

Этот вопрос был вызван replie (s)сообщение от Херб Саттер где он объяснил решение MS не поддерживать / создавать компилятор C99, а просто использовать возможности C (99), которые в любом случае входят в стандарт C ++ (11).

Одинкомментатор ответил:

(...) C is important and deserves at least a little bit of attention.

There is a LOT of existing code out there that is valid C but is not valid C++. That code is not likely to be rewritten (...)

Поскольку я программирую только на MS C ++, я действительно не знаю, "чистый" ли он? С этим хорошо, то есть у меня нет готовой картины того, какие детали языка C ++, который я использую, отсутствуют в C (99), и у меня есть небольшие подсказки, где некоторый код C99 не будет работать как есть в компиляторе C ++.

Обратите внимание, что я знаю только о C99restrict Ключевое слово, которое для меняseems иметь очень узкое применение и использовать массивы переменной длины (из которых я не уверен, насколько они распространены или важны).

Кроме того, меня очень интересует, существуют ли какие-либо важные семантические различия или ошибки, то есть код C (99), который будетcompile в C ++ (11), но с компилятором C ++ сделать что-то иначе, чем с компилятором C.

Быстрые ссылки: Внешние ресурсы из ответов:

Wikipedia page David R. Tribble's comparison (from 2001) C++11 standard: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3376.pdf (section C.1)
david.tribble.com/text/cdiffs.htm - многое из этого по-прежнему действует для C ++ 11. @CodyGray: VLA не являются частью C ++ 11. Mat
"Обратите внимание, что я знаю ... о массивах переменной длины". Niklas B.
Я видел это и чувствовал, что он не может знать, что такое массив переменной длины, если не может представить, как они будут полезны или важны. :-) Cody Gray♦
@CodyGray: C ++ 11 не поддерживает VLA, поэтому ваш комментарий может быть ответом :) Alok Save
Поддерживает ли C ++ 11 массивы переменной длины? C99 делает, так что если нет, то это довольно хороший пример. Cody Gray♦

Ваш Ответ

4   ответа
26

иногда называемого чистым C (что не совсем C90), вы должны рассмотреть 3 типа несовместимости:

Additional C++ featues which make legal C illegal C++

Examples for this are C++ keywords which can be used as identifiers in C or conversions which are implicit in C but require an explicit cast in C++.

This is probably the main reason why Microsoft still ships a C frontend at all: otherwise, legacy code that doesn't compile as C++ would have to be rewritten.

Additional C features which aren't part of C++

The C language did not stop evolving after C++ was forked. Some examples are variable-length arrays, designated initializers and restrict. These features can be quite handy, but aren't part of any C++ standard, and some of them will probably never make it in.

Features which are available in both C and C++, but have different semantics

An example for this would be the linkage of const objects or inline functions.

Список несовместимостей между C99 и C ++ 98можно найти здесь (который уже был упомянут Матем).

В то время как C ++ 11 и C11 стали ближе по некоторым направлениям (в C ++ теперь доступны переменные макросы, массивы переменной длины теперь являются необязательной функцией языка C), список несовместимостей также вырос (например, общие выборки в C иauto спецификатор типа в C ++).

Кроме того, в то время как Microsoft взяла некоторое тепло для решения отказаться от C (который не является недавним), насколько я знаю, никто в сообществе открытого источника фактически не предпринял шаги, чтобы что-то с этим сделать: это было бы вполне возможно обеспечить многие возможности современного C с помощью компилятора C-to-C ++, особенно если учесть, чтонекоторые из них тривиальны для реализации, На самом деле это возможно прямо сейчас, используя Comeau C / C ++, который поддерживает C99.

Однако это на самом деле не является насущной проблемой: лично мне вполне удобно использовать GCC и Clang в Windows, и есть также проприетарные альтернативы MSVC, например, Pelles C или компилятор Intel.

2
,

члена является неопределенным поведением, тогда как это не является неопределенным в C99.

Есть много других отличий, перечисленных в Википедиистраница.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededstackoverflow.com/a/8513748/48015
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededen.wikipedia.org/wiki/…Error: User Rate Limit Exceeded Martin Ba
Error: User Rate Limit Exceededreinterpret_castError: User Rate Limit Exceededunsigned intError: User Rate Limit ExceededfloatError: User Rate Limit Exceededreinterpret_castError: User Rate Limit Exceeded
29

которые существуют уже целую вечность (C90 или ранее), а также куча действительно хороших функций в C99 и C11. Это все с моей головы.

// 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 is nice and C programmers everywhere should use it

Новые функции в C99 очень хороши для общего программирования. VLA иrestrict не (на мой взгляд) предназначены для общего использования, но в основном для привлечения FORTRAN и числовых программистов на C (хотяrestrict помогает автовекторизатор). Так как любая соответствующая программа, которая используетrestrict будет работать точно так же (но, возможно, не так быстро), если вы#define restrict вверху файла это не имеет большого значения. VLA довольно редко встречаются в дикой природе.

Flexible array members can be nice.  Обратите внимание, что они НЕ совпадают с массивами переменной длины! Люди используют этот трюк годами, но официальная поддержка означает меньшее количество набираемых текстов, а также позволяет нам создавать константы во время компиляции. (Старый способ состоял в том, чтобы иметь массив размера 1, но тогда вычисление размера выделения - настоящее беспокойство.)

struct lenstr {
    unsigned length;
    char data[];
};
// compile time constant
const struct lenstr hello = { 12, "hello, world" };

Designated initializers.  Экономит много печатать.

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

The inline keyword ведет себя по-разному, вы можете выбрать, какой модуль перевода получает не встроенную версию функции, объявленной как встроенную, добавив объявление extern к этому модулю.

Compound literals.

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 находится в C ++ 11, но все еще заметно отсутствует в среде выполнения MSVC C.)

Anonymous structures and unions (C11, но расширение GCC с тех пор навсегда) (анонимные союзы, видимо, в C ++ 03, в режиме C поддержка MSVC отсутствует):

struct my_value {
    int type;
    union {
        int as_int;
        double as_double;
    }; // no field name!
};

Как вы можете видеть, многие из этих функций просто сэкономят вам много времени на набор текста (составные литералы) или упростят отладку программ (гибкие члены массива), упростят избежание ошибок (назначенные инициализаторы / забывающие инициализировать поля структуры). Это не радикальные изменения.

Что касается семантических различий, я уверен, что правила наложения имен различны, но большинство компиляторов в наши дни достаточно прощают, я не уверен, как вы создадите тестовый пример для демонстрации. Разница между C и C ++, к которой все стремятся, заключается в старомsizeof('a') выражение, которое всегда 1 для C ++, но обычно 4 для 32-битной системы C. Но никого не волнует, чтоsizeof('a') в любом случае. Однако в стандарте C99 есть некоторые гарантии, которые кодифицируют существующие практики.

Возьми следующий код. Он использует общий прием для определения типов объединения в C, не тратя впустую дополнительное хранилище. яthink это семантически действительный C99 и яthink это семантически сомнительный C ++, но я могу ошибаться.

#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.  Генератор кода MSVC хороший, слишком плохой, нет внешнего интерфейса C99.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededreturn {cos(angle)*r,sin(angle)*r};Error: User Rate Limit Exceeded
Error: User Rate Limit ExceededtagError: User Rate Limit ExceededunionError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededhave toError: User Rate Limit Exceeded
2

Стандарт C ++ 11, Этот документ наносит удар по каждому различию и его влиянию на развитие.

Похожие вопросы