Annex C (informative) Compatibility [diff]

C.1 C++ and ISO C [diff.iso]

C.1.6 Clause [dcl.dcl]: declarations [diff.dcl]

[dcl.stc]
Изменение: В C ++ спецификаторы static или extern могут применяться только к именам объектов или функций.
Использование этих спецификаторов с объявлениями типов недопустимо в C ++. В C эти спецификаторы игнорируются при использовании в объявлениях типов.

Пример:

static struct S {               // valid C, invalid in C++
  int i;
};


Обоснование: спецификаторы класса хранилища не имеют никакого значения, когда они связаны с типом. В C ++ члены класса могут быть объявлены с помощью static спецификатора класса хранения. Разрешение указателей класса хранения в объявлениях типов может сбить с толку пользователей.
Влияние на исходный объект: удаление семантически четко определенного объекта.
Сложность преобразования: синтаксическое преобразование.
Насколько широко используется: редко.

[dcl.stc]
Изменение: в C ++ register не является спецификатором класса хранения.
Обоснование: спецификатор класса хранения не действует в C ++.
Влияние на исходный объект: удаление семантически четко определенного объекта.
Сложность преобразования: синтаксическое преобразование.
Насколько широко используется: Обычный.

[dcl.typedef]
Изменение: имя typedef C ++ должно отличаться от любого имени типа класса, объявленного в той же области (кроме случаев, когда typedef является синонимом имени класса с тем же именем). В C имя typedef и имя тега структуры, объявленные в одной области, могут иметь одно и то же имя (потому что у них разные пространства имен).

Пример:

typedef struct name1 { /* ... */ } name1;         // valid C and C++
struct name { /* ... */ };
typedef int name;               // valid C, invalid C++


Обоснование: Для простоты использования, C ++ не требует , чтобы имя типа с префиксом ключевых слов class, struct или union при использовании в объявлениях объектов или слепков типа.

Пример:

class name { /* ... */ };
name i;                         // i has type class name


Влияние на исходный объект: удаление семантически четко определенного объекта.
Сложность преобразования: семантическое преобразование. Необходимо переименовать один из двух типов.
Насколько широко используется: редко.

[dcl.type] [см. также [basic.link]]
Изменение: const объекты должны быть инициализированы в C ++, но могут быть оставлены неинициализированными в C.
Обоснование: объект const не может быть назначен, поэтому он должен быть инициализирован для хранения полезного значения.
Влияние на исходный объект: удаление семантически четко определенного объекта.
Сложность преобразования: семантическое преобразование.
Насколько широко используется: редко.

[dcl.type]
Изменение: неявный запрет int.

В C ++ a decl-specifier-seq должен содержать a type-specifier, если за ним не следует декларатор для конструктора, деструктора или функции преобразования. В следующем примере в левом столбце представлен действительный C; в правом столбце представлен эквивалентный C ++:

void f(const parm);            void f(const int parm);
const n = 3;                   const int n = 3;
main()                         int main()
    /* ... */                      /* ... */


Обоснование: В C ++ неявное int создает несколько возможностей для двусмысленности между выражениями, включающими функционально-подобные приведения и объявления. Явное объявление все чаще считается правильным стилем. Связь с WG14 (C) указала на поддержку (по крайней мере) отказа от неявного int в следующей версии C.
Влияние на исходную функцию: удаление семантически четко определенной функции.
Сложность преобразования: синтаксическое преобразование. Можно автоматизировать.
Насколько широко используется: Обычный.

[dcl.spec.auto]
Изменение: ключевое слово auto нельзя использовать в качестве спецификатора класса хранения.

void f() {
  auto int x;     // valid C, invalid C++
}


Обоснование: разрешение использовать auto для определения типа переменной из ее инициализатора приводит к нежелательной интерпретации auto в качестве спецификатора класса хранения в определенных контекстах.
Влияние на исходный объект: удаление семантически четко определенного объекта.
Сложность преобразования: синтаксическое преобразование.
Насколько широко используется: редко.

[dcl.enum]
Изменение: объектам C ++ перечислимого типа могут быть присвоены значения только одного и того же перечислимого типа. В C объектам перечислимого типа могут быть присвоены значения любого целочисленного типа.

Пример:

enum color { red, blue, green };
enum color c = 1;               // valid C, invalid C++


Обоснование: типобезопасная природа C ++.
Влияние на исходный объект: удаление семантически четко определенного объекта.
Сложность преобразования: синтаксическое преобразование. (Ошибка типа, вызванная назначением, может быть автоматически исправлена ​​путем применения явного приведения.)
Насколько широко используется: Часто.

[dcl.enum]
Изменение: В C ++ тип перечислителя - это его перечисление. В C тип перечислителя int.

Пример:

enum e { A };
sizeof(A) == sizeof(int)        // in C
sizeof(A) == sizeof(e)          // in C++
/* and sizeof(int) is not necessarily equal to sizeof(e) */


Обоснование: В C ++ перечисление - это отдельный тип.
Влияние на исходную функцию: изменение семантики четко определенной функции.
Сложность преобразования: семантическое преобразование.
Насколько широко используется: редко. Единственный раз, когда это влияет на существующий код C, - это когда берется размер перечислителя. Взятие размера перечислителя - не обычная практика кодирования C.