массив объявлен с ключевым словом static: что такое static, указатель или весь массив? - PullRequest
7 голосов
/ 13 января 2011

Простой, но хитрый вопрос:

void f() {
    static int a[3] = {1, 2, 3};
    ...

Что здесь статического?Указатель на массив или весь массив?

Может кто-нибудь указать мне определение этого в стандарте C?

Спасибо!

Ответы [ 3 ]

6 голосов
/ 13 января 2011

Из стандарта ISO C99 (раздел 6.2.1, «Области применения идентификаторов»):

3 Если объявление области видимости файла идентификатор объекта или функции содержит класс хранения спецификатор статический, идентификатор имеет внутренняя связь.22)

В вашем примере это идентификатор a, который становится статическим (то есть символ в объектном файле не экспортируется).

EDIT:

Для статических объявлений не в файловой области (раздел 6.2.4, «Длительность хранения объектов»)

3 Объект, идентификатор которого заявлено с внешним или внутренним связь, или с классом хранения спецификатор static имеет статическое хранилище продолжительность. Его время жизни целиком выполнение программы и ее сохраненное значение инициализируется только один раз, до запуска программы.

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

2 голосов
/ 13 января 2011

Это относится к массиву.В вашем коде нет указателя.Массив не указатель.

#include <stdlib.h>
#include <stdio.h>

void f() {
    static int a[3] = {1, 2, 3};
        a[1]++;
        printf("%d\n", a[1]);
}

main()
{
        int i;
        for (i = 0; i < 5; i++)
        {
                f();
        }
}

вывод

3
4
5
6
7
2 голосов
/ 13 января 2011

В коде:

static int a[3] = {1, 2, 3};

Тип для является не указателем, а массивом типа int. Однако он автоматически преобразуется в указатель, например в стандарте C:

За исключением случаев, когда это операнд оператора sizeof или унарный оператор &, или строковый литерал, используемый для инициализации массива, выражение с типом «массив типа» преобразуется в выражение с типом « указатель на тип, который указывает на начальный элемент объекта массива и не является lvalue.

Так что если a является массивом, то = {1, 2, 3} это его инициализация, а не какой-то отдельный массив. Я не знаю, указано ли это где-то точно, но в этом смысле оно используется во всем стандарте.

Редактировать , чтобы устранить путаницу у некоторых читателей: согласно цитируемому стандарту, если вы напишите:

int arr[4] = { };
arr[0] = 1; //arr here has here type int*
size_t sz = sizeof(arr); //here it is not type int*, sizeof is exception
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...