define — определяет именованную константу


Define — определяет именованную константу

(PHP 3, PHP 4, PHP 5)

define — определяет именованную константу.

Описание

bool define ( string name, mixed value [, bool case_insensitive])

Определяет именованную константу. См. также раздел о константах.

Имя константы задаётся параметром name ; значение — параметром value .

Имеет также необязательный третий параметр case_insensitive . Если задано значение TRUE , константа будет определена с учётом регистра. По умолчанию — с учётом регистра; т.е. CONSTANT и Constant это разные значения.

Пример 1. Определение констант

define() возвращает TRUE при успехе и FALSE , если возникает ошибка.

Константы в С++

Константы в С++ аналогичны константам в Си. Для представления константы в Си использовалась только директива препроцессора #define :

В С++ для представления константы рекомендуется использовать объявление переменной с начальным значением и ключевым словом const :

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

const тип *ИмяПеременной;

Еще одна возможность const состоит в создании постоянного указателя на величину указанного типа
тип *const ИмяПеременной = Значение;

Использование const имеет несколько преимуществ по сравнению с #define .

  • При объявлении константы с использованием const явно указывается тип величины.
  • Константа, объявленная с использванием const , просто согласуется с производными типами, например, объявление массива:

Перечислимый тип данных

С помощью ключевого слова enum можно объявить особый целочисленный тип с набором именованных целых констант, называемых перечислимыми константами:

С помощью такого определения создается целочисленный тип day с названиями 7 дней недели, каждое из которых является целочисленной константой.

Перечислимые константы — идентификаторы, которые по умолчанию имеют следующие значения: 0, 1, 2, 3, 4, 5, 6. Первому присваивается значение 0, и каждому последующему – на 1 больше предыдущего.

Если не устраивают значения по умолчанию, то перечислимые константы могут быть инициализированы произвольными целыми константами или константными выражениями

Перечислимая константа может быть объявлена анонимно (без тега):

Почему кто-то использует #define для определения констант?

Это простой вопрос, но зачем кому-то использовать #define для определения констант?

Какая разница между


#define sum 1 и const int sum = 1;

#define имеет много разных приложений, но ваш вопрос, похоже, касается одного конкретного приложения: определение именованных констант.

В С++ редко существует причина использовать #define для определения именованных констант.

#define обычно широко используется в коде C, так как язык C существенно отличается от С++, когда дело доходит до определения констант. Короче говоря, объекты const int не являются константами в C, а это значит, что в C основным способом определения истинной константы является использование #define . (Кроме того, для констант int можно использовать перечисления).

Никто не должен! На самом деле, следует предпочесть const int sum = 1; над #define sum 1 по ряду причин:

Механизм на основе видимости:

#define не относятся к областям, поэтому нет возможности создать пространство имен с ограниченным классом. Хотя константные переменные могут быть ограничены в классах.

Избегайте странных магических чисел при ошибках компиляции:

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

Простота отладки:

Также по тем же причинам, указанным в # 2, в то время как отладка #define не даст никакой помощи.

Таким образом, чтобы избежать вышеуказанных ситуаций, const будет лучшим выбором.

В примере, который вы только что дали, я бы обычно использовал константу. За исключением, конечно, #define можно использовать для условной компиляции в другом месте:

Это то, что вы не можете сделать с константой. Если вам не нужно значение, доступное из препроцессора, я бы сказал, используйте const, если нет причин, почему это невозможно. Там некоторые вещи на этом в С++ FAQ lite, где они справедливо указывают на то, что только потому, что препроцессор «злой», это не значит вам это никогда не понадобится.

#define необходимо сделать такие вещи, как включение охранников, потому что у С++ нет реальной системы импорта модулей.

#define вызывает буквальную текстовую замену. Препроцессор понимает, как tokenize исходный код, но не имеет никакого представления о том, что на самом деле означает это. Когда вы пишете #define sum 1 , препроцессор просматривает ваш код и ищет каждый экземпляр токена sum и заменяет его токеном 1 .

Это имеет ряд ограничений: #define sq(x) x * x не будет работать правильно, если вы используете его как sq(3+3) ; и использование #define для константы никак не относится к сфере видимости и не связывает какой-либо тип с константой. Тем не менее, #define может использоваться (особенно в сочетании с некоторыми другими специальными элементами, такими как операторы препроцессора # и ## ), чтобы сделать магию, которая в противном случае невозможна (за исключением того, что вручную выполняет то, что делает препроцессор).

Всегда пытайтесь использовать «const int», а не #define.

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

Также это единственный способ определить что-то, что будет проверено позже, # if/# else/# endif

Это означает, что sum не существует после завершения этапа предварительной обработки.

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

const int — это просто int, который не может измениться. #define — это директива для препроцессора C, которая намного больше, чем просто для определения констант.

Во-первых, это директива препроцессора, прежде чем компилятор компилирует ваш код, он перейдет и заменит сумму на 1. Вторая объявляет переменную в памяти для хранения этого количества. Я уверен, что можно утверждать, что лучше, но «const int», вероятно, более распространен в С++ (когда дело доходит до числовых констант).

Посмотрите другие вопросы по меткам c++ c-preprocessor const или Задайте вопрос

Оператор Const (Visual Basic) Const Statement (Visual Basic)

Объявляет и определяет одну или несколько констант. Declares and defines one or more constants.


Синтаксис Syntax

Части Parts

attributelist
Необязательный. Optional. Список атрибутов, которые применяются ко всем константам, объявленным в этой инструкции. List of attributes that apply to all the constants declared in this statement. См. список атрибутов в угловых скобках (» » и » > «). See Attribute List in angle brackets (» » and » > «).

accessmodifier
Необязательный. Optional. Используйте его, чтобы указать, какой код может получить доступ к этим константам. Use this to specify what code can access these constants. Может быть общедоступным, защищенным, дружественным, защищенным дружественным, частнымили частным. Can be Public, Protected, Friend, Protected Friend, Private, or Private Protected.

Shadows
Необязательный. Optional. Используйте его для повторного объявления и скрытия программного элемента в базовом классе. Use this to redeclare and hide a programming element in a base class. См. раздел Shadows. See Shadows.

constantlist
Обязательный. Required. Список констант, объявляемых в этой инструкции. List of constants being declared in this statement.

constant [ , constant . ] constant [ , constant . ]

Каждый элемент constant имеет перечисленные ниже синтаксис и компоненты. Each constant has the following syntax and parts:

constantname [ As datatype ] = initializer constantname [ As datatype ] = initializer

Отделение Part Описание Description
constantname Обязательный. Required. Имя константы. Name of the constant. См. раздел Declared Element Names. See Declared Element Names.
datatype Требуется, если Option Strict On . Required if Option Strict is On . Тип данных константы. Data type of the constant.
initializer Обязательный. Required. Выражение, которое вычисляется во время компиляции и присваивается константе. Expression that is evaluated at compile time and assigned to the constant.

Заметки Remarks

Если у вас есть значение, которое никогда не изменяется в приложении, можно определить именованную константу и использовать ее вместо литерального значения. If you have a value that never changes in your application, you can define a named constant and use it in place of a literal value. Имя проще запомнить, чем значение. A name is easier to remember than a value. Вы можете определить константу только один раз и использовать ее во многих местах кода. You can define the constant just once and use it in many places in your code. Если в более поздней версии необходимо переопределить значение, то только Const ная инструкция является единственным местом, которое необходимо внести в изменение. If in a later version you need to redefine the value, the Const statement is the only place you need to make a change.

@No__t_0 можно использовать только на уровне модуля или процедуры. You can use Const only at module or procedure level. Это означает, что контекст объявления для переменной должен быть классом, структурой, модулем, процедурой или блоком и не может быть исходным файлом, пространством имен или интерфейсом. This means the declaration context for a variable must be a class, structure, module, procedure, or block, and cannot be a source file, namespace, or interface. Дополнительные сведения см. в разделе Контексты объявления и уровни доступа по умолчанию. For more information, see Declaration Contexts and Default Access Levels.

Локальные константы (внутри процедуры) по умолчанию имеют открытый доступ, и в них нельзя использовать какие-либо модификаторы доступа. Local constants (inside a procedure) default to public access, and you cannot use any access modifiers on them. Константы класса и члена модуля (вне любой процедуры) по умолчанию имеют частный доступ, а константы членов структуры по умолчанию имеют открытый доступ. Class and module member constants (outside any procedure) default to private access, and structure member constants default to public access. Уровни доступа можно изменить с помощью модификаторов доступа. You can adjust their access levels with the access modifiers.

Правила Rules

Контекст объявления. Declaration Context. Константа, объявленная на уровне модуля вне любой процедуры, является константой-членом; Он является членом класса, структуры или модуля, объявляющего его. A constant declared at module level, outside any procedure, is a member constant; it is a member of the class, structure, or module that declares it.

Константа, объявленная на уровне процедуры, является локальной константой; Он является локальным для процедуры или блока, объявляющего ее. A constant declared at procedure level is a local constant; it is local to the procedure or block that declares it.

Атрибута. Attributes. Атрибуты можно применять только к константам членов, а не к локальным константам. You can apply attributes only to member constants, not to local constants. Атрибут вносит сведения в метаданные сборки, что не имеет смысла для временного хранения, например локальных констант. An attribute contributes information to the assembly’s metadata, which is not meaningful for temporary storage such as local constants.

Модификаторы. Modifiers. По умолчанию все константы — это Shared , Static и ReadOnly . By default, all constants are Shared , Static , and ReadOnly . При объявлении константы нельзя использовать какие-либо из этих ключевых слов. You cannot use any of these keywords when declaring a constant.

На уровне процедуры нельзя использовать Shadows или модификаторы доступа для объявления локальных констант. At procedure level, you cannot use Shadows or any access modifiers to declare local constants.

Несколько констант. Multiple Constants. Можно объявить несколько констант в одном операторе объявления, указав constantname часть для каждого из них. You can declare several constants in the same declaration statement, specifying the constantname part for each one. Несколько констант разделяются запятыми. Multiple constants are separated by commas.

Правила типов данных Data Type Rules

Типы данных. Data Types. Оператор Const может объявлять тип данных переменной. The Const statement can declare the data type of a variable. Можно указать любой тип данных или имя перечисления. You can specify any data type or the name of an enumeration.

Тип по умолчанию. Default Type. Если не указать datatype , константа принимает тип данных initializer . If you do not specify datatype , the constant takes the data type of initializer . Если заданы и datatype , и initializer , тип данных initializer должен быть преобразован в datatype . If you specify both datatype and initializer , the data type of initializer must be convertible to datatype . Если ни datatype , ни initializer не указаны, по умолчанию используется тип данных Object . If neither datatype nor initializer is present, the data type defaults to Object .

Различные типы. Different Types. Можно указать различные типы данных для разных констант, используя отдельное предложение As для каждой объявляемой переменной. You can specify different data types for different constants by using a separate As clause for each variable you declare. Однако нельзя объявить несколько констант, имеющих один и тот же тип, используя общее предложение As . However, you cannot declare several constants to be of the same type by using a common As clause.

Инициализации. Initialization. Необходимо инициализировать значение каждой константы в constantlist . You must initialize the value of every constant in constantlist . Используйте initializer , чтобы указать выражение, присваиваемое константе. You use initializer to supply an expression to be assigned to the constant. Выражение может быть любым сочетанием литералов, других уже определенных констант и уже определенных элементов перечисления. The expression can be any combination of literals, other constants that are already defined, and enumeration members that are already defined. Для объединения таких элементов можно использовать арифметические и логические операторы. You can use arithmetic and logical operators to combine such elements.

В initializer нельзя использовать переменные или функции. You cannot use variables or functions in initializer . Однако можно использовать ключевые слова преобразования, такие как CByte и CShort . However, you can use conversion keywords such as CByte and CShort . Можно также использовать AscW , если он вызывается с константой String или аргументом Char , так как это может быть вычислено во время компиляции. You can also use AscW if you call it with a constant String or Char argument, since that can be evaluated at compile time.


Поведение Behavior

Которых. Scope. Локальные константы доступны только в пределах их процедуры или блока. Local constants are accessible only from within their procedure or block. Константы членов доступны из любого места в своем классе, структуре или модуле. Member constants are accessible from anywhere within their class, structure, or module.

Квалификацию. Qualification. Код за пределами класса, структуры или модуля должен уточнять имя константы-члена именем этого класса, структуры или модуля. Code outside a class, structure, or module must qualify a member constant’s name with the name of that class, structure, or module. Код за пределами процедуры или блока не может ссылаться на любые локальные константы в этой процедуре или блоке. Code outside a procedure or block cannot refer to any local constants within that procedure or block.

Пример Example

В следующем примере оператор Const используется для объявления констант для использования вместо литеральных значений. The following example uses the Const statement to declare constants for use in place of literal values.

Пример Example

Если вы определяете константу с типом данных Object , компилятор Visual Basic присваивает ему тип initializer , а не Object . If you define a constant with data type Object , the Visual Basic compiler gives it the type of initializer , instead of Object . В следующем примере константа naturalLogBase имеет тип времени выполнения Decimal . In the following example, the constant naturalLogBase has the run-time type Decimal .

В предыдущем примере используется метод ToString для объекта Type, возвращаемого оператором GetType, так как Type не может быть преобразован в String с помощью CStr . The preceding example uses the ToString method on the Type object returned by the GetType Operator, because Type cannot be converted to String using CStr .

PHP — именованные константы (define) плюсы и минусы

В рамках данной статьи, я расскажу про плюсы и минусы использования именованных констант (define) в языке программирования PHP.

Немногим ранее, я уже писал про автозагрузку и поддержку динамических имен переменных в PHP. Это весьма гибкие и удобные механизмы, однако чье некорректное использование может существенно усложнить код или же и вовсе привести к проблемам безопасности. Поэтому в продолжении этих материалов, я хотел бы упомянуть об еще одном весьма полезном и удобном механизме — именованные константы (объявляемые с помощью define).

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

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

Есть основной файл index.php

И есть какой-нибудь файл движка engine.php, где в первых же строках проверяется наличие этой константы

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

Примечание: Конечно, стоит понимать, что это не панацея. Если у взломщика есть возможность менять или создавать файлы, или же у вас в коде ошибки, или же вы где-то оставили тестовый файл php, то такая защита не очень-то и поможет.

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

Однако, есть ряд нюансов, которые необходимо понимать, в противном случае из удобного механизма очень легко получить массу проблем (приведу парочку).

1. Константы нельзя переопределять.

Это же очевидно скажете вы, но суть тут заключается в другом. Представьте, что вы создали свою библиотеку из 100 файлов, где направо и налево использовали константы (гибкость же!). Однако, часть констант либо может определяться пользователем, чтобы сконфигурировать действия (суть проста — не определена константа — один вариант действий, определена — другой), либо используется чуть ли не во всем проекте. При этом часть констант построены по принципу расширения имени, когда в имени дополнительной уточняющей константы указывается основное имя и некий дополнительный префикс.

Вы все оттестировали, померили скорость, порадовались результату и прочее.

Прошло время и люди стали использовать вашу библиотеку не только в своих самописных проектах, но и в дополнении к различным CMS. Все радовались и бегали по лужам. Однако, в один момент оказалось, что в одной из CMS была добавлена константа в файле конфигурации, из-за которой библиотека сыпалась с «Fatal Error». После долгих разбирательств, вы обнаружили, что смело использовали короткое и удобное название одной из констант.

А теперь, представьте сколько времени займет замена одной этой несчастной константы? Впрочем, такая проблема говорит о необходимости полной замены имен констант, но об этом чуть далее. Отвечая на вопрос, нет это не только «Поиск и замена» в любом из редакторов (к примеру, Notepad++). Это так же и полная перепроверка всей функциональности, плюс оповещение пользователей, чтобы они смогли переконфигурировать вашу библиотеку в своих проектах.

Таким образом, вы всегда должны помнить, что ваши константы должны иметь уникальные имена (префикс библиотеки или нечто подобное), тем самым превращаясь в длинные строки (нередко константы бывают и длиной по 100-120 символов). В противном случае, всегда будут проблемы с интеграцией.

2. Используемых для настройки констант должно быть ограниченное и вменяемое количество.

Если вы что-то писали под CMS или же просто интересовались доступными настройками, то, вероятно, замечали что их порядка 10-20, несмотря на огромные объемы кода. Конечно, же всегда существуют и системные константы для удобства использования, которые можно встретить только лишь в самом ядре системы, но сути это не меняет.


Если количество констант в вашем коде становится слишком много, то со временем использовать такой код становится практически невозможно. И тут есть несколько причин.

Во-первых, проблема первичной конфигурации. Если открывали хоть раз ini файл конфигурации самого PHP, то видели сколько там различных параметров. А теперь, представьте, что все они не были бы заполнены относительно универсальными параметрами, а так же посмотрите сколько в интернете статей про настройку и сколько времени люди тратят на решение банальных проблем «кривой конфигурации». «Ну и что?» — скажете вы. Только тут есть один важный момент — PHP это инструмент мирового масштаба, причем не предназначенный для обычных пользователей.

Во-вторых, вопрос архитектуры. Если в коде есть большое количество констант, то это один из признаков, что архитектура проекта имеет проблемы. И речь не идет о количестве настроек. Так, например, в любой CMS с кучей установленных модулей, настроек невероятно много. Однако, все эти настройки распределены между разными механизмами, такими как банальная таблица в БД. Поэтому код остается читаемым, легко настраиваемым и относительно универсальным.

В-третьих, вопрос корректировки кода. Каждое исправление или же корректировка кода с необходимостью добавления, редактирования или удаления констант будет весьма неожиданным сюрпризом для других пользователей. А все банально потому, что если требуется переконфигурация или импорт старых настроек, то сделать это будет нереально, так как «где, как и что» пользователь использовал, вы не можете заранее определить.

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

3. Константы не хранят объекты, только простые данные.

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

Но, возвращаясь. Другими словами, константы это механизмы функционального подхода. Это означает, что если вы применяете ООП, то наросты констант с настройками будут лишь существенно усложнять код. Что-то вроде этого:

Такой подход невероятно усложняет поиск ошибок и проблем, особенно учитывая то, что сами эти PARAM`s могут определяться динамически.

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

Как видите, у именованных констант есть свои нюансы, которые необходимо учитывать.

[C++] define как определение константы vs. макроса

На всякий случай. Это не константа, а макрос

Комментарий модератора
Начало здесь: Директива препроцессора #if
09.08.2012, 08:09

Как происходит формирование константы типа #define?
Подскажите, пожалуйста, как происходит формирование константы типа #define и почему использование.

Массив, константы и #define
Всем доброго дня! Сразу к делу. Есть большое желание иметь массив длиной в константу и саму эту.

Define внутри макроса
Подкажите возможно ли написать макрос кот. создаст #define? например: #define MACRO(name) .

Вывести значение макроса #define
Здравствуйте. Возникла проблема с #define. Нужно каким-нибудь способом вывести на экран значение.

[C++] Директива #define. В виде макроса определен шаблон функции.
Здравствуйте! Есть проблема и мне она непонятна! В программке присутствует директива #define.

11.08.2012, 13:06 141

— ну так а почему суёшь свои 5 копеек в обсуждение темы для тех у кого она была?

Скрин пришлю 17-го числа (за ним надо ехать к родителям(я не живу сейчас обложившись книгами и словорями), как раз к ним тогда собираюсь). Как вариант накачай себе словарей из интернета и посмотри смысл слова manifest

В любом случае даже руководствуясь твоим переводом стандарт чётко оговаривает эту макроподстановку как

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

PS:Уже для другого ответчика ШУРа, я могу ответить тебе твоим же постом,пойми я увидел то что ты много лет в стандарте пропускал, а теперь ты просто по этому поводу бесишься )))

11.08.2012, 13:10 142

11.08.2012, 13:17 143

слушай вот скажи ты английскй в инсте изучал?У тебя лекции на нём были, ты часть диплома на нём отвечал и защищал?

— ну ты видишь что сам стандарт говорит «объявленной константы», ОМГ

Добавлено через 3 минуты
PS:Пойми 2000 результатов поиска в гугле define и Именованная константа не появились бы просто так, не надо тут всех кто так пишет называть тупыми, надо просто подумать а не лить на меня помои!

11.08.2012, 13:18 144
11.08.2012, 13:18
11.08.2012, 13:19 145
11.08.2012, 19:13 146

Технический термин именованной константы это «Named Constant». «manifest constant» — переводите как хотите, хоть именованная константа, хоть декларативная константа, хоть явная константа или предопределенная константа. Но отличайте общепринятые технические определение от игры слов. В русском языке просто нельзя подобрать подобный эпитет, чтобы он привычно звучал в контексте. Для наглядности на русском, к примеру, есть фраза «он собаку съел на этом». У этой фразы может быть два значение: «он имеет большой опыт» или «он реально ел собаку». Первый смысл — это технический термин, второе — это обычное предложение. При переводе эти фразы будут иметь одинаковые слова, но смысл будет разный. Тут же даже слова разные.

Добавлено через 2 минуты
Вот решил глянуть в гугле, что есть manifest constant. К примеру технический перевод. Если не в курсе рдтех — это известная организация, которая кроме много чего еще, занимается переводом оракловой документации. И довольно успешно.
К чему это все, называйте ее хоть именованной константой — нутро у нее макрос.

Функция Define

Функция Define определяет именованную константу.
Функция Define определяет именованную константу во время выполнения.

В параметре Name содержится имя константы.

Функция Define позволяет определить константы с зарезервированными или даже некорректными именами, значения которых могут быть (только) получены через функцию Constant.

В параметре Value указывается значение константы. С версии PHP 7 значение константы, кроме Integer, Float, String, Boolean или NULL, могут также использовать тип Array.

Если параметр Case_insensitive установлен как TRUE, то константа будет определена без учета регистра. По умолчанию константа чувствительна к регистру. Начиная с PHP 7.3.0, определение нечувствительных к регистру констант объявлено устаревшим и будет удален в версии 8.0.0.

Функция Define возвращает TRUE в случае успешного завершения или FALSE в случае возникновения ошибки.

Пример использования функции Define:

Именованные константы и макроопределения

Читайте также:

  1. A.числовые переменные и константы, объединенные знаками арифметических операций
  2. Для константы скорости бимолекулярной реакции получаем
  3. Константы
  4. Константы
  5. Константы
  6. Константы нестойкости комплексных ионов
  7. Символьные константы
  8. Среднее значение константы скорости реакции
  9. Таким образом, логический закон можно определить как выражение, содержащее только логические константы и переменные и являющееся истинным в любой (непустой) области объектов.
  10. Термодинамические константы некоторых веществ
  11. Числовые константы

Директива #define обычно используется для замены часто используемых в программе констант, ключевых слов, операторов и выражений осмысленными идентификаторами. Идентификаторы, которые заменяют числовые или текстовые константы либо произвольную последовательность символов, называются именованными константами. Идентификаторы, которые представляют некоторую последовательность действий, заданную операторами или выражениями языка Си, называются макроопределениями. Макроопределения могут иметь аргументы. Обращение к макроопределению в программе называется макровызовом.

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

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

Макроопределение напоминает по синтаксису определение функции. Однако замена вызова функции макровызовом может повысить скорость выполнения программы, поскольку для макроопределения не требуется генерировать вызывающую последовательность, которая занимает относительно большое время (засылка аргументов в стек, передача управления и т.п.). С другой стороны, многократное употребление макроопределения в программе может потребовать значительно большей памяти, чем вызовы функции (код для функции генерируется один раз, а для макроопределения — столько раз, сколько имеется макровызовов в программе).

Имеется возможность задавать определения именованных констант не только в исходном тексте, но и в командной строке компиляции.

Имеется ряд предопределенных идентификаторов, которые нельзя использовать в директивах #define и #undef в качестве идентификаторов. Они рассмотрены в разделе 7.9 «Псевдопеременные».


7.2.1 Директива #define

Директива #define заменяет все вхождения в исходном файле на , следующий в директиве за . Этот процесс называется макроподстановкой, заменяется лишь в том случае, если он представляет собой отдельную лексему. Например, если является частью строки или более длинного идентификатора, он не заменяется. Если за следует , то директива определяет макроопределение с аргументами.

представляет собой набор лексем, таких как ключевые слова, константы, идентификаторы или выражения. Один или более пробельных символов должны отделять от (или от заключенных в скобки параметров). Если текст не умещается на строке, то он может быть продолжен на следующей строке; для этого следует набрать в конце строки символ обратный слэш и сразу за ним нажать клавишу ENTER.

может быть опущен. В этом случае все экземпляры будут удалены из исходного текста программы. Тем не менее, сам рассматривается как определенный и при проверке директивой #if дает значение 1 (смотри раздел 7.4.1).

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

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

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

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

Внутрь в директиве #define могут быть вложены имена других макроопределений или констант. Их расширение производится лишь при расширении этого , а не при его определении директивой #define. Это надо учитывать, в частности, при взаимодействии вложенных именованных констант и макроопределений с директивой #undef: к моменту расширения содержащего их текста они могут уже оказаться отменены директивой #undef.

После того как выполнена макроподстановка, полученная строка вновь просматривается для поиска других имен констант и макроопределений. При повторном просмотре не принимается к рассмотрению имя ранее произведенной макроподстановки. Поэтому директива

не приведет к зацикливанию препроцессора.

#define WIDTH 80

#define LENGTH (WIDTH + 10)

#define FILEMESSAGE «Попытка создать файл\

не удалась из-за нехватки дискового пространства»

#define REG1 register

#define REG2 register

#define MAX(x, y)((x)>(у)) ? (x) : (у)

#define MULT(a, b) ((a)*(b))

В первом примере идентификатор WIDTH определяетсякак целая константа со значением 80, а идентификатор LENGTH — как текст (WIDTH + 10). Каждое вхождение идентификатора LENGTH в исходный файл будет заменено на текст (WIDTH + 10), который после расширения идентификатора WIDTH превратится в выражение (80 + 10). Скобки, окружающие текст (WIDTH + 10), позволяют избежать ошибок в операторах, подобных следующему:

var= LENGTH * 20;

После обработки препроцессором оператор примет вид:

Значение, которое присваивается var, равно 1800. В отсутствие скобок в макроопределении оператор имел бы следующий вид:

Значение var равнялось бы 280, поскольку операция умножения имеет более высокий приоритет, чем операция сложения.

Во втором примере определяется идентификатор FILEMESSAGE. Его определение продолжается на вторую строку путем использования символа обратный слэш непосредственно перед нажатием клавиши ENTER.

В третьем примере определены три идентификатора, REG1, REG2, REG3. Идентификаторы REG1 и REG2 определены как ключевые слова register. Определение REG3 опущено и, таким образом, любое вхождение REG3 будет удалено из исходного файла. В разделе 7.4.1 приведен пример, показывающий, как эти директивы могут быть использованы для задания класса памяти register наиболее важным переменным программы.

В четвертом примере определяется макроопределение МАХ. Каждое вхождение идентификатора МАХ в исходном файле заменяется на выражение ((x)>(у))?(x):(у), в котором вместо формальных параметров х и у подставлены фактические. Например, макровызов


заменится на выражение

заменится на выражение

Обратите внимание на то, что в этом макроопределении аргументы с побочными эффектами могут привести к неверным результатам. Например, макровызов

заменится на выражение

Операнды операции > могут быть вычислены в любом порядке, а значение переменной i зависит от порядка вычисления. Поэтому результат выражения непредсказуем. Кроме того, возможна ситуация, когда переменная i будет инкрементирована дважды, что, вероятно, не требуется.

В пятом примере определяется макроопределение MULT. Макровызов MULT(3,5) в тексте программы заменяется на (3)*(5). Круглые скобки, в которые заключаются фактические аргументы, необходимы в тех случаях, когда аргументы макроопределения являются сложными выражениями. Например, макровызов

заменится на (3+4)*(5+6), что равняется 76. В отсутствие скобок результат подстановки 3+4*5+6 был бы равен 29.

Дата добавления: 2014-11-16 ; Просмотров: 299 ; Нарушение авторских прав? ;

Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет

Различие define и const

В чем различие между этими определениями переменной:

Что из этих двух является более предпочтительным и в чем достоинства каждого?

2 ответа 2

Это очень дискуссионный вопрос у всех. Но в целом, в с++ лучше использовать const везде, где это возможно.

  • на них действуют области видимости.
  • компилятор относится к ним как к обычными переменным, доступным только на чтение.
  • у них есть тип.

У define это все — недостатки. Они действуют от места определения и до . конца. Хотя, где этот конец будет — ещё нужно хорошо подумать. Они могут переопределять друг дружку и иногда искать, где именно было в очередной раз переопределено — ещё то удовольствие. Компилятор часто выдает очень «загадочные ошибки». Классический пример с макросом min/max. Файл windows.h определяет их. И может быть очень весело. Детали — NOMINMAX.

Ещё у define есть большой недостаток — это то, что некоторые думают, что там есть скобки. А их нет.

кажется, что будет посчитано (x+y) в квадрате. А на самом деле — . на самом деле x+y + x*y.

Но мы немного отвлеклись. Такого сделать обычным const уже нельзя. Но легко сделать inline функциями. И их результат будет предсказуемый.

  • eсли нужно просто определить константу — используйте const (даже само слово намекает).
  • eсли нужно определить макрос — используйте функции (если хочется интересней — используйте inline, но компиляторы сейчас достаточно умные).
  • если нужно усложнить код и добавить синтаскического сахара — тогда самое время использовать define.

UPD

А ещё хорошо найти книгу Эффективное использование C++. 55 верных советов улучшить структуру и код ваших программ — Скотт Майерс и почитать второй совет (в любом случае — там всю книгу можно читать и читать).

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

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

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


Но, опять же, такое различие существует лишь на уровне соглашений, т.е. разницы между const int и constexpr int в тривиальных применениях вы не заметите.

Однако и у #define тоже есть свои преимущества.

Ограничение на использование только либо const , либо #define варианта возникнет тогда, когда вы будете создавать кросс-компилируемый С и С++ код (например, заголовочные файлы библиотек, предназначенных для использования в обоих языках). Тогда вам в большинстве случаев придется пользоваться именно #define , ибо в языке С квалификатор const не создает констант. В языке С для создания именованных констант времени компиляции у вас есть только enum и #define .

В качестве еще одного преимущества варианта с #define можно назвать очевидную (но часто забываемую) возможность использовать #define -константы в условных выражениях препроцессора, т.е. в #if . Ни const , ни constexpr вам там не помогут. Шаблонное метапрограммирование и появление в языке С++ таких C++17 свойств, как «static if» ( if constexpr ) тоже частично переносит такие применения из области препроцессора в область самого языка и, соответственно, снижает ценность #define -констант в С++, но тем не менее эта деталь тоже заслуживает упоминания.

Имена констант и переменных

Каждой используемой в программе константе и переменной должно быть присвоено имя. Максимальная длина имени зависит от особенностей компилятора: некоторые ограничивают имя восемью символами, другие позволяют давать имена, состоящие из 32 и даже большего количества символов. В некоторых случаях имя переменной может быть гораздо длиннее, но не все составляющие его символы будут иметь значение для компилятора. Например, вы можете использовать имя, состоящее из 32 символов, но определяющими являются только первые восемь, и переменные, названные вами accountspayable и accountsreceivable, компилятор будет воспринимать как одну и ту же переменную.

Имена переменных и констант могут содержать латинские прописные или строчные буквы, а также символ подчеркивания (_). Можно использовать любые сочетания букв и цифр, но начинаться имя должно с буквы. Символ подчеркивания используют для разделения слов, чтобы сделать имя более понятным, например, city_tax вместо citytax.

Старайтесь выбирать имена переменных и констант так, чтобы они указывали на то, как будут использоваться данные. Имя city_tax содержит больше информации, чем ctax, а имя amt_due должно сказать вам больше, чем просто due. Избегайте употребления имен типа А или В кроме тех случаев, когда пишете очень простую программу.

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

Ключевые слова KR стандарта:

auto break case char continue default dodouble else entry extern float for goto if int long register return short sizeof static struct switch typedef union

В стандарте ANSI Си добавлены следующие ключевые слова:

const enum signed void volatile

Рис. 6. В языке Си приняты правила определения имен констант и переменных

В языке Си++ добавлены ключевые слова:

catch cin class cout delete friend inline new operator private protected

В именах констант и переменных учитывается регистр символа. Если вы назвали переменную TAX, вы не можете ссылаться на нее как на переменную Tax или tax. Фактически, вы получите три различные переменные с именами TAX, Tax и tax, каждая из которых имеет свое значение и относится к своему типу, что, разумеется, сильно затруднит чтение и отладку программы. Многие начинающие программисты допускают неточности в употреблении заглавных букв в именах констант и переменных в разных частях программы, что приводит к ошибкам компиляции или выполнения, которые часто бывает очень трудно найти и исправить.

В языке Си принято правило (рис. 6) использовать маленькие буквы для имен переменных, а заглавные — для имен констант. Хотя нарушение этого соглашения не приведет к ошибке компиляции, тем не менее существует веская причина подчиняться ему. Соблюдение этого простого правила позволяет легко различать константы и переменные в тексте программы, что упрощает чтение программы и облегчает понимание ее логики.

В программе должны быть определены имена и типы всех используемых переменных и констант.

Рис. 7. Синтаксис определения константы

Определить константу — это значит сообщить компилятору Си ее имя и значение. Для определения константы перед функцией main() помещают директиву #define, имеющую следующий синтаксис:

#define NAME VALUE

После директивы точка с запятой не пишется, зато необходимо вставить, по меньшей мере, по одному пробелу между директивой, именем константы и присваиваемым значением. Дополнительные синтаксические символы вводятся в зависимости от типа определяемых данных: числовых, символьных или строк (рис.7).

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

Рис. 8. Определение константы

Для определения числовой константы необходимо задать имя и значение константы. Например, директива

создает константу, называемую PI, и присваивает ей значение 3.14 (рис.8).


Везде, где компилятор в исходном тексте программы (например, в формуле) встретит имя константы PI, он подставит вместо него значение 3.14 (рис.9).

Рис. 9. Компилятор подставляет вместо имени константы ее значение

При определении константы нет необходимости специально указывать тип данных. Компилятор присвоит его на основании значения, заданного директивой #define. В приводившемся выше примере, константа PI будет отнесена к типу чисел с плавающей точкой, так как ее значение, 3.14, является вещественным числом. В директиве

компилятор отнесет константу COUNT к типу целых чисел, поскольку 5 — это целое число.

Присваивая константе значение, относящееся к типу float, проследите, чтобы ваше число имело, по меньшей мере, по одному знаку слева и справа от точки. Если само значение не имеет десятичной части, добавьте после точки пару нулей:

#define RATE 5.00

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

#define RATE 0.56

В противном случае, если будет написано #define RATE .56, неизбежна ошибка компиляции.

Значение символьного типа должно быть заключено в одинарные кавычки:

Аналогично, определяя строку, заключите значение в двойные кавычки:

#define MY_FRIEND George main()

Помните о том, что кавычки не входят в значение константы.

Когда имя константы является параметром, как с функцией puts() в нашем примере, оно не заключается в кавычки. Отсутствие кавычек указывает компилятору, что следует использовать значение, присвоенное константе с таким именем, а не символы (буквы), из которых это имя состоит. То есть в нашем случае будет использовано значение, присвоенное константе MY_FRIEND, которое соответствует строке George, а не буквы M-Y-_-F-R-I-E-N-D. Для того чтобы на экране появилось именно слово MY_FRIEND, инструкция должна быть такой:

После того как мы ввели директиву #define MY_FRIEND George, встретив в любом месте программы слово MY_FRIEND, компилятор подставит вместо него слово George, так что инструкция

на самом деле будет вызывать функцию puts() как

что приведет к появлению на экране имени George. Если ваша программа начинается со строки

#define MY_FRIEND Марина

на экране появится имя Марины. Почему? Потому что директива #define определяет константу с именем MY_FRIEND, имеющую значение Марина.

Компиляторы Си++ и некоторые компиляторы Си имеют дополнительный способ определения констант. Можно определить константу, описать тип данных и присвоить значение, используя ключевое слово const. Такое определение должно помещаться внутри тела функции, в отличие от директивы, помещаемой всегда вне его:

Использование ключевого слова const обусловлено тем, что оно позволяет программисту создавать константы, которые принадлежат одной определенной функции. Но чтобы обеспечить совместимость компиляторов Си и Си++, многие программисты продолжают использовать для определения констант директиву #define.

Приведенные инструкции определяют целочисленную константу со значением 8 и символьную константу, имеющую значение ‘C’. Их можно определить и так:

Статьи к прочтению:

Уроки Ардуино #1.1 — действия с переменными и константы

Похожие статьи:

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

Переменная – это имя, которое разработчик программы дает области компьютерной памяти, используемой для хранения данных какого-либо типа. Переменная…

Илон Маск рекомендует:  Выравнивание элементов
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL