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

StackOverflow https://stackoverflow.com/questions/3755524

  •  04-10-2019
  •  | 
  •  

Вопрос

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

Это было полезно?

Решение

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

5 + 7 / 3

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

5 + someNumber / 3

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

Другие советы

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

Например (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)];)

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

char x;
char *p = &x;

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

char *s = "foobar";

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

3     0.0f    '\n'

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

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

sizeof(char)
(byte) 15

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

15 + 3
0.0f + 0.0f
sizeof(char)

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

strlen("hello")
fifteen + x

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

/* Always a constant */
#define FIFTEEN 15

/* Only constant if (x) is
#define htons(x)  (( ((x) >> 8) | ((x) << 8) ) & 0xffff) 

/* Never constant */
#define X_LENGTH  strlen(x)

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

Еще одна забавная морщина: в 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.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top