2012-05-04 2 views
1

Правильность ли следующая декларация?Декларации класса хранения

Вне любой функции:

int a; //external by default 
extern int a; //explicitly extern 
static int a; //explicity static 
const int a; //static by default 
static const int a; //explicitly static 
extern const int a; //explicitly extern 

Внутри функции:

int a; //auto by default 
static in a; //explicity static 
const int a; //static by default 
static const int a; //explicitly static 
+0

'const' не влияет на длительность хранения или связь, т.е. те же правила применяются к переменным' const' и non-'const' ... – Christoph

+0

см. Также пример на http : //port70.net/~nsz/c/c99/n1256.html#6.9.2 о определениях файловой области ... – Christoph

ответ

2

Закрыть.

Все, что находится в глобальной области видимости (т.е. вне функции), по умолчанию статично.

например:

//main.c 
int myVar; // global, and static 

int main(void) { 
    ... 
    return 0; 
} 

//morecode.c 
extern int myVar; //other C files can see and use this global/static variable 

Однако, если вы явно объявить что-то в глобальном масштабе, как статические, она не только статические, но она видна только внутри этого файла. Другие файлы не могут его увидеть.

//main.c 
static int myVar; // global, and static 

int main(void) { 
    ... 
    return 0; 
} 

//morecode.c 
extern int myVar; // compiler error; "myVar" can only be seen by 
        // code in main.c since it was explicitly 
        // declared static at the global scope 

Кроме того, по умолчанию нет «extern». Обычно вы используете extern для доступа к глобальным переменным из других файлов, если они не были явно объявлены как статические, как в приведенном выше примере.

const означает, что данные не могут измениться, независимо от его объема. Это не означает, что внешний или статический. Что-то может быть «extern const» или «extern», но «extern static» на самом деле не имеет смысла.

В качестве последнего примера этот код будет построен на большинстве компиляторов, но он имеет проблему: myVar всегда объявляется «extern», даже в файле, который его технически создает. Неудачный пример:

//main.c 
extern int myVar; // global, and static, but redundant, and might not work 
        // on some compilers; don't do this; at least one .C file 
        // should contain the line "int myVar" if you want it 
        // accessible by other files 
int main(void) { 
    ... 
    return 0; 
} 

//morecode.c 
extern int myVar; //other C files can see and use this global/static variable 

Наконец, вы можете захотеть, чтобы покрыть этот пост на различных уровнях объема, если вы еще не знакомы с ними.Это, вероятно, будет полезно и информативно для вас. Удачи!

Terminology definition - Scope in C application

Человек, который ответил на этот вопрос мой о сфере проделал хорошую работу, на мой взгляд.

Кроме того, если вы заявляете что-то статическое внутри функции, значение остается между вызовами функций.

например:

int myFunc(int input) { 
    static int statInt = 5; 
    printf("Input:%d statInt:%d",input,statInt); 
    statInt++; 
    return statInt; 
} 

int main(void) { 
    myFunc(1); 
    myFunc(5); 
    myFunc(100); 
    return 0; 
} 

Выход:

Input:1 statInt:0 
Input:5 statInt:1 
Input:100 statInt:2 

Обратите внимание, что использование статической переменной внутри функции имеет определенное и ограниченное число случаев, когда они являются полезными, и в целом не являются хорошей идеей для большинства проектов.

+0

Является ли 'static const int i;' действительным оператором? –

+0

Да. Если вы делаете это в глобальной области видимости, вы создали переменную const, которая может быть доступна только в этом файле. Кроме того, значение может быть установлено только во время определения, поэтому единственный способ использовать то, что имеет смысл, будет выглядеть примерно так: static const int ConsCanOnlyBeSeenInThisFile = 1; например. Если вы выполняете эту функцию внутри функции, она имеет аналогичный эффект, но ее можно увидеть только в области функций. Помните, что если вы устанавливаете переменную внутри статической функции, ее значение остается неизменным между вызовами. – DevNull

1

Одно неправильное представление у вас есть, кажется, что extern является противоположностью static. Это не тот случай. У вас есть следующее:

int a; //extern by default 

Это не «extern по умолчанию». Объявление extern означает, что определение фактической переменной находится в другом месте. Так что если у вас есть это в исходном файле:

extern int a; 

Потом где-то у вас есть еще один исходный файл с:

int a; 

В противном случае, если вы компиляции кода вы получите:

/tmp/cc3NMJxZ.o: In function `main': 
foo.c:(.text+0x11): undefined reference to `a' 
collect2: ld returned 1 exit status 

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

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

... и действительно, очень простой тест подтверждает, что const не означает static.

+0

'extern' не обязательно означает, что определение находится в другом файле. И выражение extern, и определение могут быть в одном файле. 'extern' просто означает, что' Определение этой переменной существует somwhere (которое может быть где угодно) –

+0

* extern по умолчанию * является правильным, поскольку переменные области видимости по умолчанию имеют внешнюю привязку; однако связь между привязкой и спецификаторами 'extern' и' static' не так проста, как можно было бы ожидать ... – Christoph

+0

Правильно, спасибо, что сделали это более понятным. – larsks

1

Вы должны отделить понятия продолжительности хранения и связи. extern и static, в различных контекстах, могут оказывать влияние на оба этих свойства и другие эффекты, но не являются единственным определяющим фактором для любого из них.

В файле объема


int a; 

Это предварительное определение. a имеет статическую продолжительность хранения и внешнюю связь.


extern int a; 

декларация, но не определение. длительность статического хранения и внешнюю связь (или связь, определяемую предыдущим объявлением, если она видна).


static int a; 

Предварительное определение. продолжительности статического хранения и внутренней связи.


const int a; 

Предварительное заявление. статическая продолжительность хранения и внешняя связь (в отличие от C++).


static const int a; 

Предварительное определение. продолжительности статического хранения и внутренней связи.


extern const int a; 

декларация, а не определение. длительность статического хранения и внешнюю связь (или связь, определяемую предыдущим объявлением, если она видна).


В блоке рамки


int a; 

Определение. время автоматического хранения и отсутствие связи.


static int a; 

Определение. статический срок хранения и отсутствие связи.


const int a; 

Определение. время автоматического хранения и отсутствие связи. (я думаю это строго законно, но не очень полезно, поскольку вы не можете изменить неопределенное начальное значение a «s, не вызывая неопределенное поведение.)


static const int a; 

Определения. статический срок хранения и отсутствие связи. (Опять же, не очень полезно!)

+0

небольшая коррекция: 'extern int a;' в области файлов имеет только внешнюю связь, если нет предыдущего объявления с внутренней связью; также отсутствует как из вопроса, так и из ответа: внешние объявления с областью видимости – Christoph

+0

@ Кристоф: Верно, я предполагал, что это были первые (или только) декларации в соответствующих областях. –

+0

также, я бы не сказал block-scoped 'static const int a;' бесполезен - объекты со статической продолжительностью хранения неявно инициализируются нулем, поэтому значение корректно определено; Я использую такие переменные регулярно, например, для инициализации выделенных объектов. – Christoph

Смежные вопросы