Возьми этот код:
int issuecode(int i)
{
return 2 * i;
}
int main(int argc, char **argv)
{
return issuecode(argc);
}
Насколько я понимаю, если скомпилировать как программу на C, она будет иметь неопределенное поведение. Я основываюсь на этих стандартных цитатах:
С99, 7,26 (или С11, 7.31)
Следующие имена сгруппированы под отдельными заголовками для удобства. Все внешние имена, описанные ниже, зарезервированы независимо от того, какие заголовки включены в программу.
С99, 7.26.2 (или С11, 7.31.2)
Имена функций, которые начинаются с
is
или жеto
и строчные буквы могут быть добавлены к объявлениям в<ctype.h>
заголовок.
С99, 7.1.3 (или C11, 7.1.3)
Каждый заголовок объявляет или определяет все идентификаторы, перечисленные в связанном с ним подпункте, и, необязательно, объявляет или определяет идентификаторы, перечисленные в соответствующем подпункте будущих направлений библиотеки, и идентификаторы, которые всегда зарезервированы либо для любого использования, либо для использования в качестве идентификаторов области файла.
[…]
- Все идентификаторы с внешней связью в любом из следующих подпунктов (включая будущие направления библиотеки) всегда зарезервированы для использования в качестве идентификаторов с внешней связью.
- […] Если программа объявляет или определяет идентификатор в контексте, в котором она зарезервирована (кроме как разрешено в 7.1.4), или определяет зарезервированный идентификатор как имя макроса, поведение не определено.
Исходя из вышеизложенного, я считаю, что имя функции issuecode
фактически зарезервировано для использования в <ctype.h>
и поэтому программа технически имеет UB.
Вопрос 0 (проверка работоспособности): Является ли мое чтение стандарта правильным, а поведение программы технически не определено?
Вопрос 1: Будет ли программа иметь UB, если она скомпилирована как код C ++?
Я полагаю, что ответ «нет», так как из следующих цитат я бы сказал, что «будущие направления библиотеки» C не являются частью стандартной библиотеки 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>
и заголовок C Unicode TR, соответственно, со следующими модификациями:
Ни в одной из «следующих модификаций» не упоминаются дополнительные зарезервированные идентификаторы. Таблица 74 представляет собой так называемый список имен функций, таких как isdigit
а также isalnum
,
С ++ 11, С.2
1. В этом подпункте обобщено содержимое стандартной библиотеки C ++, включенной в стандартную библиотеку C. Он также суммирует явные изменения в определениях, объявлениях или поведении из библиотеки Standard C, отмеченные в других подпунктах (17.6.1.2, 18.2, 21.7).
7. Стандартная библиотека C ++ предоставляет 209 стандартных функций из библиотеки C, как показано в таблице 153.
Опять же, таблица 153 представляет собой налоговый список.
Вопрос 2: Если предположить, что я ошибаюсь в вопросе 1, и в программе действительно есть UB на C ++, повлияют ли на это следующие изменения?
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 (C ++ 11), которые являются последними общедоступными черновиками для соответствующих языковых версий.
Следующие имена сгруппированы под отдельными заголовками для удобства. Все внешние имена, описанные ниже, зарезервированы независимо от того, какие заголовки включены в программу.
Существует предопределенный список функций, которые зарезервированы, если ваша функция не конфликтует с именами, в этом нет проблем.
Имена функций, начинающиеся с is или to, и строчные буквы могут быть добавлены в объявления в <ctype.h> заголовок.
Оперативный термин есть может быть добавленным к <ctype.h>
заголовок. Бит «is or to» — это просто руководство по организации объявлений.
Так что на самом деле там никогда не было неопределенного поведения …
Что касается C ++, я думаю, что это следует той же идее, например:
namespace foo{
int isupper ( int c );
}
#include <cctype>
using namespace foo;
int main(void){
isupper(92);
}
Это должно приводить к ошибке компилятора, потому что ваша функция сталкивается с именем с функцией C, но из-за пространства имен это легко исправить, добавив std::
или foo::
к началу разговора.
C ++ 11 17.6.1.2 Заголовки
172) Заголовки стандартной библиотеки C (Приложение D.5) также определяют имена в глобальном пространстве имен, тогда как заголовки C ++ для C
библиотечные средства (17.6.1.2) может также определить имена в глобальном пространстве имен.В стандартной библиотеке C ++, однако, объявления (за исключением
имена, которые определены как макросы в C), находятся в пределах области имен (3.3.6) пространства имен std. это
неопределенные будут ли эти имена сначала объявлены в глобальной области имен, а затем введены
в пространство имен std с помощью явных объявлений using (7.3.3).
Так что, если вы не включите <cctype>
поведение четко определено. Если вы делаете, это не указано.