действительно ли использовать стандартное имя библиотечной функции в качестве идентификатора в C ++?

Рассмотрим следующую программу:

#include <cstdio>
int main()
{
int printf=9;
std::printf("%d",printf);
}

Можно ли использовать имя встроенной функции в качестве идентификатора в объявлении переменной? Это четко определенная программа? Я имею в виду, хорошо ли определено поведение вышеуказанной программы Мне любопытно узнать, позволяет ли стандарт C ++ использовать стандартные имена функций в качестве идентификаторов переменных

1

Решение

Это хорошо сформировано, потому что ни std::printf ни ::printf (который может также были объявлены <cstdio>!) объявляются в той же области видимости, что и ваше целое число, поэтому автоматическое преимущество имеет продолжительность блока.

[C++14: 3.3.1/1]: [..] Чтобы определить объем объявления, иногда удобно обратиться к потенциальному объему объявления. Область объявления совпадает с ее потенциальной областью, если только потенциальная область не содержит другую декларацию с тем же именем. В этом случае потенциальная область объявления во внутренней (содержащейся) декларативной области исключается из области действия декларации во внешней (содержащей) декларативной области.

Например, как правило, вы не сможете сделать это в области имен.

Он четко определен, потому что имена объектов в стандартной библиотеке не являются зарезервированными по своей природе:

[C++14: 2.11/3]: Кроме того, некоторые идентификаторы зарезервированы для использования реализациями C ++ и стандартными библиотеками (17.6.4.3.2) и не должны использоваться иначе; Диагностика не требуется.

[C++14: 17.6.4.3.2/1]: Определенные наборы имен и сигнатур функций всегда зарезервированы для реализации:

  • Каждое имя, которое содержит двойное подчеркивание _ _ или начинается с подчеркивания, за которым следует заглавная буква (2.12), зарезервировано для реализации для любого использования.
  • Каждое имя, которое начинается со знака подчеркивания, зарезервировано для реализации для использования в качестве имени в глобальном пространстве имен.
4

Другие решения

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

4

Технически это разрешено делать. Есть имена, которые зарезервированы в глобальном пространстве имен, но внутри функции ваше имя переменной не будет видно вне функции, так что это не проблема.

Это ужасная идея, чтобы использовать это.

И будьте осторожны, что могут быть проблемы с этим подходом. Например:

#define NULL 0

int main()
{
int NULL = 42;
printf("%d", NULL);
}

не допускается, так как NULL является макросом, а не идентификатором области видимости.

Изменить: я бы добавил, что printf не является «встроенной функцией». Это «стандартная библиотечная функция C». Функция bultin это что-то вроде __builtin_sin, о котором «знает» компилятор, чтобы его можно было оптимизировать. Обратите внимание, что встроенные функции обычно используют «зарезервированные имена», чтобы избежать столкновения с существующей библиотекой и пользовательскими именами в любое время.

3

По сравнению с идентификаторами в стандартных библиотеках стандарт C ++ устанавливает только следующую реструктуризацию для идентификаторов.

3 Кроме того, некоторые идентификаторы зарезервированы для использования C ++
реализации и стандартные библиотеки (17.6.4.3.2) и не должно быть
используется иначе; Диагностика не требуется.

И (17.6.4.3.2 Глобальные имена)

1 Определенные наборы имен и сигнатур функций всегда зарезервированы для
реализация:

— Каждое имя, которое содержит двойное подчеркивание _ _ или начинается с
подчеркивание, за которым следует заглавная буква (2.12), зарезервировано для
реализация для любого использования.

— Каждое имя, начинающееся с подчеркивания, зарезервировано для
реализация для использования в качестве имени в глобальном пространстве имен.

Таким образом, вы можете использовать идентификаторы, которые совпадают со стандартными именами функций.

С другой стороны, это может запутать читателей кода и привести к неоднозначности.
Примите во внимание, что Стандарт позволяет компиляторам размещать имена стандартных функций Си в глобальном пространстве имен.

0

Это нормально, чтобы сделать это. Потому что переменная int printf вы определили не принадлежат к пространству имен std как printf, который определен в cstdio, Таким образом, в именах вашей программы нет конфликта.

Однако, если вы объявите

using namespace std;

до вашей программы, и нет std:: позже в вашей программе, тогда это вызовет проблемы, если вы не будете осторожны. Обычно, когда есть конфликты имен, компилятор будет использовать имя, определенное в наименьшей области видимости. Так что, если у вас есть программа вроде:

#include<cstdio>
using namespace std;

int main()
{
int printf = 42;
printf("%d", printf);
}

Компилятор вернет

error: ‘printf’ cannot be used as a function

Это потому, что в этой программе printf определяется как int в объеме функции, и как функция int printf( const char* format, ... ) в глобальном масштабе. Так как область действия функции меньше глобальной области видимости, в функции int main(), printf интерпретируется как int а не функция. int не вызывается, поэтому сообщение об ошибке.

0
По вопросам рекламы [email protected]