Пример чего-то, что есть и не является «константным выражением» в C?
====================================================================

Я немного запутался между тем, что есть и не является константным выражением в C, даже после долгих поисков в Google. Не могли бы вы привести пример чего-то, что является, а что нет, выражением константы в C?

Постоянное выражение может быть оценено во время компиляции. Это означает, что в нем нет переменных. Например:

это постоянное выражение. Что-то вроде:

нет, при условии`someNumber` является переменной (т. е. не является константой времени компиляции).



Любой однозначный литерал является константным выражением.

(Строковые литералы странные, потому что они на самом деле массивы. Кажется,`"hello"` на самом деле не является константой, так как в конечном итоге приходится связывать и все такое, а адрес и содержимое могут меняться во время выполнения.)

Большинство операторов (sizeof, приведений и т. Д.), Применяемых к константам или типам, являются константными выражениями.

Любое выражение, включающее только константные выражения, само по себе также является константным выражением.

Любое выражение, включающее вызовы функций или неконстантные выражения, обычноне постоянное выражение.

Статус любого макроса как константного выражения зависит от того, к чему он расширяется.

У меня изначально было кое-что здесь о`const` идентификаторы, но я проверял это и, видимо, это не относится к C.`const`как ни странно, не объявляет константы (по крайней мере, не достаточно «константные» для использования в`switch` заявления). В C ++, однако, это так.



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

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



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

Например`(24*60*60)` может быть вычислено обоими, но`sizeof struct foo` известен только компилятору. Это различие может иметь значение, если вы пытаетесь проверить, что`struct` определяется для соответствия внешнему обязательному размеру или для того, чтобы его элементы отображались с заданными внешними смещениями. (Этот вариант использования часто возникает при кодировании драйверов устройств, когда`struct` описывает регистры устройства как расположенные в области памяти.)

В этом случае вы не можете просто сказать`#if (sizeof(struct UART) == 12)` потому что препроцессор работает с опережением компиляции и просто не может знать размер каких-либо типов. Это, однако, константное выражение и будет допустимым в качестве инициализатора для глобальной переменной (например,`int UARTwords = sizeof(struct UART) / sizeof(short);`) или объявить размер массива (например,`unsigned char UARTmirror[sizeof(struct UART)];`)



Еще одна забавная маленькая морщинка: в C значение enum является константой, но ее можно использовать только после завершения объявления enum. Следующее, например, не приемлемо в стандарте C, хотя это приемлемо в C ++:

```
enum {foo=19, bar, boz=bar+5;};

```
Это может быть переписано:

```
enum {foo=19, bar}; enum {boz=bar+5;};

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



Также`integral character constants` как`'a'` или же`'\n'` являются константами, которые компилятор распознает как таковые. У них есть тип`int`.