Ответ 1
Правильно ли я предполагаю
#define РАЗМЕР 5
а также
const int SIZE = 5;коренным образом отличаются друг от друга?
Да ты прав.
#define
- это просто текстовая замена. В принципе, препроцессор C собирается "найти и заменить" для вас во время процесса компиляции (этап обработки). В то время как объект const
означает, что "вещь, хранящаяся в этом месте, не может быть изменена", что примерно эквивалентно утверждению "только для чтения".
#define РАЗМЕР 5
int arr [SIZE] = {11, 22, 33, 44, 55};действительный синтаксис.
Это в точности эквивалентно написанию:
int arr[5] = {11, 22, 33, 44, 55};
сам. Компилятор просто выполняет замещающее задание для вас, когда вы используете define
.
const int SIZE = 5;
int arr [SIZE] = {11, 22, 33, 44, 55};
Недопустимый синтаксис.
Это недействительно, но причина может быть более одной. Если arr
имеет статическую продолжительность хранения (т. arr
Объект arr
жив во время выполнения программы), то он недействителен. Поскольку C требует, чтобы размер объекта массива со статической продолжительностью хранения был постоянным выражением:
Если размер представляет собой целочисленное константное выражение, а тип элемента имеет известный постоянный размер, тип массива не является массивом переменной длины; в противном случае тип массива представляет собой тип массива переменной длины.
Таким образом, следующая программа недействительна:
const int SIZE = 5;
int arr[SIZE] = {11, 22, 33, 44, 55};
int main(void)
{
}
потому что SIZE
не квалифицируется как "постоянное выражение" в C. Обратите внимание, что это полностью справедливо в C++, где SIZE
квалифицируется как константное выражение (здесь разные языки).
Другая причина - стандарт C не позволяет инициализировать массивы переменной длины. Если у вас есть определение внутри функции, например:
Тип инициализируемого объекта должен быть массивом неизвестного размера или полным типом объекта, который не является массивом переменной длины.
Поэтому, если у вас нет инициализатора, он становится действительным:
int main(void)
{
const int SIZE = 5;
int arr[SIZE]; /* This is OK */
}
Точно так же вы можете обойтись без const
:
int main(void)
{
int SIZE = 5;
int arr[SIZE]; /* Thi is OK too. */
}
В обоих вышеописанных фрагментах arr
является просто массивом переменной длины.
Хотя интересно,
const int SIZE = 5; int arr [SIZE];
действительный синтаксис.
Он действителен только в том случае, если он внутри функции (как указано выше) - это VLA. Но если у вас есть статическая продолжительность хранения, такая как:
const int SIZE = 5;
int arr[SIZE]; /* arr has static storage duration just as
all objects defined at file scope */
int main(void)
{
}
он недействителен, поскольку, как отмечено выше, SIZE
не является "постоянным выражением" в C.
Так же,
int main(void)
{
const int SIZE = 5;
static int arr[SIZE]; /* arr has static storage duration */
}
является недопустимым по той же причине, несмотря на то, что arr
находится внутри функции, поскольку arr
имеет статическую продолжительность хранения.
Однако, если у вас есть:
enum {SIZE = 5};
int arr[SIZE] = {11, 22, 33, 44, 55};
int arr2[SIZE]; /* Valid without initializer too. */
int main()
{
}
это действительно. Зачем? Поскольку константы перечислимого типа квалифицируются как "постоянные выражения" в C.