Сколько расширяет расширяемость библиотеки C для С++-программ? - программирование
Подтвердить что ты не робот

Сколько расширяет расширяемость библиотеки C для С++-программ?

Возьмите этот код:

int issuecode(int i)
{
  return 2 * i;
}

int main(int argc, char **argv)
{
  return issuecode(argc);
}

Как я понимаю, если он скомпилирован как программа на C, он будет иметь поведение undefined. Я полагаюсь на эти стандартные кавычки:

C99, 7.26 (или C11, 7.31)

Для удобства следующие имена сгруппированы под отдельными заголовками. Все внешние имена, описанные ниже, зарезервированы независимо от того, какие заголовки включены программой.

C99, 7.26.2 (или C11, 7.31.2)

Названия функций, начинающиеся с is или to, а строчные буквы могут быть добавлены к объявлениям в заголовке <ctype.h>.

C99, 7.1.3 (или C11, 7.1.3)

  • Каждый заголовок объявляет или определяет все идентификаторы, перечисленные в его связанном подпункте, и, возможно, объявляет или определяет идентификаторы, перечисленные в его связанных будущих указателях библиотек, подпункты и идентификаторы, которые всегда зарезервированы либо для любого использования, либо для использования в качестве идентификаторов области файла.

    [...]

    • Все идентификаторы с внешней связью в любом из следующих подклассов (включая будущие направления библиотек) всегда зарезервированы для использования в качестве идентификаторов с внешней связью.
  • [...] Если программа объявляет или определяет идентификатор в контексте, в котором он зарезервирован (кроме как разрешено в соответствии с 7.1.4), или определяет зарезервированный идентификатор в качестве имени макроса, поведение undefined.

Исходя из вышесказанного, я считаю, что имя функции issuecode фактически зарезервировано для использования в <ctype.h>, и поэтому программа технически имеет UB.

Вопрос 0 (проверка работоспособности): Является ли мое стандартное чтение и поведение программы технически undefined?

Вопрос 1: Будет ли программа иметь UB, если она скомпилирована как код на С++?

Я считаю, что ответ "нет", как из следующих цитат, я бы сказал, что "будущие направления библиотек" C не являются частью стандартной библиотеки С++, но я не уверен.

С++ 11, 21.7

  • В таблицах 74, 75, 76, 77, 78 и 79 описываются заголовки <cctype>, <cwctype>, <cstring>, <cwchar>, <cstdlib> (символьные преобразования) и <cuchar>, соответственно.

  • Содержимое этих заголовков должно совпадать с заголовками стандартной библиотеки C <ctype.h>, <wctype.h>, <string.h>, <wchar.h> и <stdlib.h> и заголовком TRC Unicode, соответственно, со следующими изменениями:

Ни одна из "последующих изменений" не упоминает дополнительные зарезервированные идентификаторы. Таблица 74 представляет собой налоговый список имен функций, таких как isdigit и isalnum.

С++ 11, C.2

1. В этом подпункте суммируется содержимое стандартной библиотеки С++, включенное в стандартную библиотеку C. Он также суммирует явные изменения в определениях, декларациях или поведении из библиотеки Standard C, отмеченные в других подпунктах (17.6.1.2, 18.2, 21.7).

7. Стандартная библиотека С++ предоставляет 209 стандартных функций из библиотеки C, как показано в таблице 153.

Снова таблица 153 является налоговым списком.

Вопрос 2: Предполагая, что я ошибаюсь в вопросе 1, и у программы действительно есть UB на С++, повлияет ли это на следующее изменение?

namespace foo {

  int issuecode(int i)
  {
    return 2 * i;
  }

}

using namespace foo;

int main(int argc, char **argv)
{
  return issuecode(argc);
}

Примечание. Стандартные кавычки взяты из черновиков N1256 (C99), N1570 (C11) и N3242 (С++ 11), которые являются последними общедоступными черновиками для соответствующих языковых версий.

4b9b3361

Ответ 1

Для удобства следующие имена сгруппированы под отдельными заголовками. Все внешние имена, описанные ниже, зарезервированы независимо от того, какие заголовки включены программой.

Существует предопределенный список зарезервированных функций, если ваша функция не конфликтует по имени, нет проблем.

Названия функций, начинающиеся с или есть, или, и строчная буква может быть добавлена ​​к объявлениям в < ctype.h > заголовок.

В заголовок <ctype.h> добавляется оператор может. Бит "есть или до" - это просто руководство по организации объявлений.

Так что там действительно не было undefined поведения...

Что касается С++, я думаю, что это следует за той же идеей, например:

namespace foo{
  int isupper ( int c );
}

#include <cctype>
using namespace foo;
int main(void){
    isupper(92);
}

Это должно привести к ошибке компилятора, потому что ваша функция сталкивается с именем мудрый с помощью функции C, но из-за пространства имен это легко можно устранить, добавив std:: или foo:: к началу вызова.

Ответ 2

С++ 11 17.6.1.2 Заголовки

172). Заголовки стандартной библиотеки C (Приложение D.5) также определяют имена в глобальном пространстве имен, а заголовки С++ для C библиотеки (17.6.1.2) может также определять имена в глобальном пространстве имен.

Однако в стандартной библиотеке С++ объявления (кроме имена, которые определены как макросы в C) находятся в области пространства имен (3.3.6) пространства имен std. Это unspecified, объявляются ли эти имена сначала в области глобального пространства имен и затем вводятся в пространство имен std с помощью явных использования-деклараций (7.3.3).

Итак, если вы не включили <cctype>, поведение будет четко определено. Если вы это сделаете, это не указано.