В этой статье от Гуру недели говорится: It is illegal to #define a reserved word.
Это правда? Я не могу найти ничего в норме, и, например, я уже видел, как программисты переопределяют новое.
Законно ли переопределять ключевое слово C ++?
Ответы (5)
17.4.3.1.1 Имена макросов [lib.macro.names]
1 Каждое имя, определенное как макрос в заголовке, зарезервировано для реализации для любого использования, если единица трансляции включает заголовок. 164)
2 Единица трансляции, которая включает заголовок, не должна содержать никаких макросов, которые определяют объявленные или определенные имена в этом заголовке. Такая единица перевода также не может определять макросы для имен, лексически идентичных ключевым словам.
Кстати, new
- это оператор, и он может быть перегружен (заменен) пользователем, указав свою версию.
#define new
, если моя единица перевода не содержит заголовков: P? @JamesKanze: почему стандартные заголовки?
- person qdii; 02.02.2012
#define while for
до включения <algorithm>
. Стандарт также требует, чтобы определенные функции были макросами, поэтому даже переопределение ключевого слова после включения заголовка может повлиять на ситуацию.
- person James Kanze; 02.02.2012
Соответствующий раздел из C ++ 11:
17.6.4.3.1 Имена макросов [macro.names]
1 Единица перевода, которая включает заголовок стандартной библиотеки, не должна #define или #undef имен, объявленных в каком-либо заголовке стандартной библиотеки.
2 Единица перевода не должна #define или #undef имен, лексически идентичных ключевым словам.
Пункт 1 из C ++ 03 был удален. Второй абзац разделен на две части. В первой половине теперь конкретно указано, что она применяется только к стандартным заголовкам. Второй пункт был расширен и теперь включает любые единицы перевода, а не только те, которые включают заголовки.
Однако в Обзор для этого раздела стандарта (17.6.4.1 [constraints.overview]) указано:
В этом разделе описаны ограничения для программ C ++, использующих возможности стандартной библиотеки C ++.
Следовательно, если вы не используете стандартную библиотеку C ++, то можете делать то, что хотите.
Итак, чтобы ответить на ваш вопрос в контексте C ++ 11: вы не можете определить (или отменить определение) какие-либо имена, идентичные ключевым словам, в любой единице перевода, если вы используете стандартную библиотеку C ++.
int main() {}
стандартную библиотеку C ++? Я спрашиваю об этом, потому что [basic.start.main] / 5 упоминает std::exit
.
- person L. F.; 09.11.2019
Они на самом деле ошибаются или, по крайней мере, не рассказывают об этом всей истории. Настоящая причина, по которой он запрещен, заключается в том, что он нарушает правило одного определения (которое, кстати, также упоминается как вторая причина, почему это незаконно).
Чтобы убедиться, что это действительно разрешено (переопределять ключевые слова), по крайней мере, если вы не используете стандартные библиотеки, вы должны взглянуть на совершенно другую часть стандарта, а именно на этапы перевода. В нем говорится, что входные данные только разлагаются на токены препроцессора перед предварительной обработкой и, глядя на них, нет различий между private
и fubar
, они оба identifiers
для препроцессора. Позже, когда ввод раскладывается на token
, замена уже произошла.
Было указано, что существует ограничение для программ, которые должны использовать стандартные библиотеки, но не очевидно, что пример, переопределяющий private
, делает это (в отличие от фрагмента «Человек # 4: Языковой юрист», который использует его для вывод в cout
).
В последнем примере упоминается, что этот трюк не попирается другими единицами перевода или не попирает другие. Имея это в виду, вам, вероятно, следует рассмотреть возможность того, что стандартная библиотека используется где-то еще, что приведет к действию этого ограничения.
Вот небольшая вещь, которую вы можете сделать, если не хотите, чтобы кто-то использовал goto. Просто оставьте следующее в его коде, где он этого не заметит.
#define goto { int x = *(int *)0; } goto
Теперь каждый раз, когда он пытается использовать оператор goto, его программа вылетает.
goto
это плохо, вы не должны писать программы, если бы вы могли убедить меня, что нельзя использовать goto
, я буду очень удивлен.
- person Iharob Al Asimi; 18.04.2015
goto
- person chbaker0; 19.04.2015
goto
, создание ненадежной ошибки времени выполнения - глупый способ сделать это. Если вы должны это сделать, сделайте это ошибкой времени компиляции: #define goto @
- person Keith Thompson; 19.04.2015
goto
не обязательно лучший способ реализовать конечный автомат; оператор switch в цикле делает текущее состояние явным. См. этот ответ для более подробного обсуждения того, когда подходит goto
.
- person Keith Thompson; 19.04.2015
#define goto { int x = *(int volatile *)0; } goto
. Тем не менее, он будет расширен как 2 оператора и вызовет синтаксические ошибки в if (xx) goto yy; else ...
. Он заслуживает большего количества голосов против за нанесение вреда языку.
- person chqrlie; 19.04.2015
Насколько мне известно, это незаконно - ни один компилятор, с которым я еще не сталкивался, не выдаст ошибку, если вы это сделаете.
#define true false
#defining
определенные ключевые слова могут вызывать ошибки при компиляции по другим причинам. Но многие из них просто приведут к очень странному поведению программы.
#define
для изменения значений зарезервированных слов. Фактически, он часто использовался в записях Международного конкурса запутанного кода C. Это возможно, потому что макросы, определенные#define
, заменяются отдельной программой перед запуском реального компилятора C. - person Some programmer dude   schedule 02.02.2012#define new newMac
на Macintosh и#define new newPc
на ПК. В других единицах трансляции соответствующие функции будут определять распределители памяти, зависящие от платформы. Я предполагаю, что идея заключалась в том, чтобы продолжать использоватьnew
повсюду, имея поведение, зависящее от платформы, когда невозможно было переименовать каждый вызов в новый. - person qdii   schedule 02.02.2012for
в Visual Studio 6, с помощью#define for if (false) else for
- person Jack Aidley   schedule 04.03.2013#define
? Или вы имеете в виду перегрузку оператораnew
? Это две очень разные вещи. - person Code-Apprentice   schedule 25.06.2013#define new newPS3
. Индустрия видеоигр может немного походить на зоопарк. - person qdii   schedule 25.06.2013