Const массивы в C
Оригинальный вопрос:
Если я определяю:
const int z[5] = {10, 11, 12, 13, 14};
означает ли это:
- это постоянный массив целых чисел, то есть адрес, который указывает z, всегда постоянный и никогда не может меняться, но элементы z могут меняться.
ИЛИ
- Каждый элемент z является константой, т.е. их значение никогда не может измениться.
Edit:
Дополнительная информация:
Существует еще одна переменная:
const int *y = z;
func((int *) y);
где func определяется как:
void func(int y[]) {
int i;
for(i = 0; i < 5; i++) {
y[i] = i; //y[i] can be set to any integer; used i as example
}
}
где в func, используя y, массив перемещается и каждый элемент изменяется. Действительно ли это верно, хотя все элементы z являются const?
Ответы
Ответ 1
Это означает, что каждый элемент z
доступен только для чтения.
Объект z
является объектом массива, а не объектом указателя; это ни на что не указывает. Как и любой объект, адрес z
не меняется в течение срока его службы.
Поскольку объект z
является массивом, выражение z
в большинстве, но не во всех контекстах неявно преобразуется в выражение указателя, указывающее на z[0]
. Этот адрес, как и адрес всего объекта массива z
, не изменяется в течение времени жизни объекта. Это "преобразование" является корректировкой значения выражения во время компиляции, а не преобразованием типов во время выполнения.
Чтобы понять (часто путающие) отношения между массивами и указателями, прочитайте раздел 6 comp.lang.c FAQ.
Важно понимать, что "константа" и const
- две разные вещи. Если что-то постоянно, оно оценивается во время компиляции; например, 42
и (2+2)
являются константными выражениями.
Если объект определен с помощью ключевого слова const
, это означает, что он доступен только для чтения, а не (обязательно), что он постоянный. Это означает, что вы не можете пытаться изменить объект через его имя, а попытка изменить его другими способами (например, путем взятия его адреса и приведения к неконстантному указателю) имеет неопределенное поведение. Обратите внимание, например, что это:
const int r = rand();
действителен. r
только для чтения, но его значение нельзя определить до времени выполнения.
Ответ 2
В вашем случае ответ:
- Каждый элемент z является константой, т.е. их значение никогда не может измениться.
Вы не можете создать массив const
, потому что массивы являются объектами и могут создаваться только во время выполнения, а const
сущности разрешаются во время компиляции.
Итак, const
интерпретируется как в первом примере ниже, т.е. применяется для элементов массива. Это означает, что следующие эквиваленты:
Массив в вашем примере должен быть инициализирован.
int const z[5] = { /*initial (and only) values*/};
const int z[5] = { /*-//-*/ };
Это некоторый тип коммутативное свойство спецификатора const
и спецификатор типа в вашем примере int
.
Вот несколько примеров, поясняющих использование константы:
1. Определение целочисленных целых чисел: (нельзя переназначить). В приведенном ниже выражении использование const
эквивалентно:
int const a = 3; // after type identifier
const int b = 4; // equivalent to before type qualifier
2. Определение указателя константы (без арифметики указателей или переопределения):
int * const p = &anInteger; // non-constant data, constant pointer
и определение указателя константе int
(значение цельного числа не может быть изменено, но указатель может):
const int *p = &anInteger; // constant data, non-constant pointer