2013-07-10 4 views
1

У меня есть несколько сомнений относительно использования ключевого слова extern с переменными в C. Я действительно просматривал ссылки, связанные с этим вопросом. Тем не менее, есть еще несколько вещей, которые я не собирайте очень хорошо
Как определяются внешние переменные?

#include<stdio.h> 
    main() 
    { 
    extern int i; 
    printf ("\n%d ",i)) ; 
    } 
    int i = 31 ; 

В приведенном выше коде, как же я получаю отпечатано до его утверждения определения?
Теперь в следующем коде:

#include<stdio.h> 
int x = 21 ; 
main() 
{extern int i; 
i=20; 
printf ("\n%d ", i) ; 
} 

Не является ли утверждение "я = 20;" утверждение определения? Я получаю сообщение об ошибке. Это потому, что я пытаюсь изменить переменную, определенную в каком-то другом исходном файле? Если это так, то как это утверждение «int i = 31;» в самом верхнем фрагменте кода право использовать?

Кроме того, я читал: «int i;» является определением. Я действительно не понимаю, как это сделать.

ответ

5

В вашей первой программе заявление на печать печатает значение i на основании декларации extern int i. Это похоже на вызов функции, основанной на ее декларации прототипа, не видя ее определения. Компилятор генерирует код для извлечения значения в глобальной переменной с именем i. Символ разрешен к правильной переменной и адресу во время соединения.

В вашей второй программе не предусмотрено определение для i, только декларация extern int i и попытка установить ее значение с помощью i = 20. Во время соединения это не удается, поскольку нет определения, и поэтому попытка разрешить ссылку на глобальную переменную не выполняется. Изменение на int i = 20 вместо этого создает локальную переменную с именем i в рамках функции main() и больше не ссылается на объявленные во всем мире extern int i.

Когда int i; используется в глобальном масштабе, он рассматривается как декларация и может рассматриваться как своего рода определение. Глобальная переменная, объявленная с инициализатором, например:

int i = 20; 

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

int i; 

рассматривается как декларация. Если появляется более одного из этих объявлений, все они рассматриваются как объявления одной и той же переменной. В то же время, если нет объявления с инициализатором, эта переменная неявно определяется с инициализатором 0, и компоновщик сможет разрешить ссылки на него.

1

Во второй программе вы не указали переменную нигде, а не вне основного, и вместо этого вы определили ее внутри основного, чтобы получить эту ошибку.

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

int i; - это объявление определения переменной как для переменных AUTO (т.е.е внутри основной или любой функции), но не для внешних переменных для extern переменных вы должны объявить, что нравится:

extern int i;

, а затем определить внешнюю магистраль, как это:

int i;

0

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

Это не имеет большого смысла в вашем втором случае, так как i определяется как локальная переменная. Если бы вы определили его как глобальный, как в первом случае, все будет хорошо.

Если я могу продемонстрировать использование extern с очень простым (надуманным) случаем:

main.c:

#include <stdio.h> 

extern int a; /* we tell the compiler that a will come from outside the scope of where it is used */ 

int main() 
{ 
    printf("%d\n", a); 

    return 0; 
} 

source.c:

int a = 3; /* we define a here */ 

Вы затем компилировать как .c Файлы:

$ gcc main.c source.c 

Этот выход 3.

Возможно, вы также захотите прочитать статью this.

+0

Я считаю, что оба должны скомпилировать, но второй из них не будет связывать (* срабатывает clang для его проверки *) – Christoph

+1

ok, первый пример не удалось скомпилировать, но не из-за объявлений переменных - есть посторонняя закрывающая скобка ... – Christoph

+0

@ Кристоф второй из-за ошибки говорит, что 'i' является' extern', но на самом деле не обеспечивает его одновременное использование. Прокомментируйте все строки, в которых '' '' 'extern', и он будет компилироваться. – Nobilis

1

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

Принятие определения, когда мы определяем переменную/функцию, помимо роли объявления, также выделяет память для этой переменной/функции.

Итак, в первой программе int i = 31 вне main() определяет переменную i. Затем эта переменная просто объявляется как внешняя переменная внутри main(). Следовательно, программа работает.

Во второй программе, не определяя переменную i в другом месте, она непосредственно объявляется как внешняя переменная. Следовательно, это дает ошибку.