В C, если это не адресная константа, что это? - PullRequest
4 голосов
/ 26 сентября 2010

Что именно означает numbers в следующем объявлении, если это не адресная константа?

int main() {
    int numbers[3] = {1,2,3};
    return 0;
}

Разборка программы показывает, что 1, 2 и 3 динамически размещаются на локальномпространство стека, а не весь массив, который рассматривается как константа.Следовательно, {1,2,3} не имеет статической длительности хранения, поэтому numbers является , а не адресной константой согласно спецификации C99.

C99, раздел 6.6.9: «Адресконстанта - это нулевой указатель, указатель на l-значение, обозначающее объект статической длительности хранения, или указатель на указатель функции ... "

Однако добавление строки numbers++ после объявления приводит к следующемуошибка компиляции в GCC 4.1.2:

error: invalid lvalue in increment

Так что это константа, но не адресная константа.Кто-нибудь знает официальное название этого типа константы в C99 (или аналогичном)?

Ответы [ 5 ]

10 голосов
/ 26 сентября 2010

Похоже, вы изобретаете что-то, чего нет в терминах терминологии.

numbers - это массив.Это автоматический объект типа int[3].Его нельзя использовать для формирования адресных констант в C, так как в C адресные константы требуют объектов со статической длительностью хранения.

Если ваш numbers был объявлен со статической продолжительностью хранения, то это результат массива-указателяпреобразование, примененное к numbers, будет константой адреса.В этом случае numbers + 1 и &numbers[2] также будут постоянными адреса.

Вы правильно заметили, что { 1, 2, 3 } не имеет статической длительности хранения.На самом деле он вообще не имеет срока хранения.Это не объект, а просто кусочек синтаксического сахара под названием агрегатный инициализатор .Если вы хотите, чтобы он стал анонимным объектом, вы должны использовать синтаксис составной литерал : (int[]) { 1, 2, 3 }, но в любом случае это не сработает.

numbers++ не будет компилироваться просто потому, что результат преобразования массива в указатель не является lvalue.Вы не можете применить ++ к non-lvalue.Является ли что-то постоянным или нет, не имеет значения.

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

8 голосов
/ 26 сентября 2010

numbers - это непостоянная автоматическая переменная массива функции main.

Поскольку она автоматическая и не постоянная, она не может иметь статическое хранилище.

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

Обратите внимание, что вы можете делать

int main() {
    int numbers[3] = {1,2,3};
    int *n = numbers+1;
    n++;
    return 0;
}
3 голосов
/ 26 сентября 2010

Массивы не являются указателями; см. раздел 6 comp.lang.c FAQ .

0 голосов
/ 26 сентября 2010

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

Это тоже не переменная, поэтому вы не можете увеличивать ее. Это просто имя места хранения, которое является смещением базового указателя. numbers[0] - это действительное значение l, но numbers - нет.

0 голосов
/ 26 сентября 2010

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

...