объявление/описание внешней переменной

Модератор: Модераторы разделов

Аватара пользователя
Dudraug
Сообщения: 313
ОС: Debian lenny/sid

объявление/описание внешней переменной

Сообщение Dudraug »

Читал вот книгу Кернигана и Ритчи. Прочел что внешняя переменная должна быть описана только один раз, для всех файлов. А для остальных надо прописать extern.
То есть такой код неправильный
main.h


main.c

Код: Выделить всё

#include "main.h"
int main()
{
    i = 5;
    funct();
    return 0;
}


funct.c

Код: Выделить всё

#include "main.h"

void funct()
{
    i =3;
}



То есть для funct.c надо сделать отдельное объявление
extern int i;
Я верно понял идею?
P4-3.0, ASUS P5GD1, 1024MB OЗУ, GeForce 6600GT
Спасибо сказали:
Аватара пользователя
deninok
Сообщения: 585
Статус: Программист С++
ОС: Debian GNU/Linux

Re: объявление/описание внешней переменной

Сообщение deninok »

А что такое int a в main.h? Ты, наверное, имел в виду int i?
Да и вообще, пример твой какой-то мутный... И дело не только во внешних переменных.
Ты вызываешь в main.c функцию void funct()? И откуда же по-твоему компилятор возьмет ее определение? Ведь тело этой функции находится в другой единице трансляции (соответствующей файлу funct.c), и к main.c она не имеет никакого отношения.
А идея с внешними переменными, по сути своей, проста. Если у тебя есть переменная int x, глобальная для некой единицы трансляции, и ты хочешь сделать эту переменную внешней, то есть видимой (и могущей быть использованной) в других единицах трансляции, то определена она должна быть, разумеется, только один раз, в своей единице трансляции. А во всех других, где данная переменная нужна, объявляем ее как внешнюю, с помощью ключевого слова extern.

Пример.

main.c

Код: Выделить всё

#include <stdio.h>

int x = 10;

int main() {
    if ( /* некоторое условие истинно */ ) {
        x = 20;
    }
    return 0;
}


angle.c

Код: Выделить всё

extern int x;

while ( x > 5 ) {
    /* Выполняем некоторое действие */
}


azimuth.c

Код: Выделить всё

extern int x;

void calc() {
    if ( x == 3 ) {
        /* сделать нечто очень важное */
    }
}


Идея, думаю, ясна. Во всех трех единицах трансляции (компилируемых, как ты знаешь, независимо друг от друга) используется одна и та же переменная int x. Она создается в main.c один раз, а из других мест, в частности, из angle.c и azimuth.c на нее ссылаются как на внешнюю, то есть созданную где-то в другой единице трансляции.

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

Важное замечание: ключевое слово extern должно быть частью объявления, а не определения. Если ты напишешь в angle.c так: extern int x = 45;, то слово extern будет проигнорированно! Потому что ты создаешь переменную, какой же смысл объявлять ее внешней? Внешняя на то и внешняя, что создается в другой единице трансляции.
Спасибо сказали:
Аватара пользователя
Dudraug
Сообщения: 313
ОС: Debian lenny/sid

Re: объявление/описание внешней переменной

Сообщение Dudraug »

да, ща поправлю
P4-3.0, ASUS P5GD1, 1024MB OЗУ, GeForce 6600GT
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: объявление/описание внешней переменной

Сообщение drBatty »

Dudraug писал(а):
20.01.2008 13:39
То есть такой код неправильный
вобще-то правильный. main.h включается в main.c Но если вы включите main.h куда нибудь ещё, вы получите такое сообщение от линкера:multiple definition of `var_name' То есть вы пытаетесь дважды объявить переменную. Поэтому в h файлах не должно быть объявления. Но может быть описание:
extern int i; если вы хотите, что-бы i было видно везде, куда вы включите .h файл. Но объявить всё равно где нибудь придётся(в одном из .с файлов).
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
Dudraug
Сообщения: 313
ОС: Debian lenny/sid

Re: объявление/описание внешней переменной

Сообщение Dudraug »

Да и вообще, пример твой какой-то мутный... И дело не только во внешних переменных.
Ты вызываешь в main.c функцию void funct()? И откуда же по-твоему компилятор возьмет ее определение? Ведь тело этой функции находится в другой единице трансляции (соответствующей файлу funct.c), и к main.c она не имеет никакого отношения.


Так я и говорю, я хочу их по отдельности скомпилить, а потом слиновать. Тогда по идее я не должен подключать main.h к funct.c а прописать в нем extern int i;
потом просто скомпилить их по отдельности, а потом слинковать?
ну или

Код: Выделить всё

gcc main.c funct.c -o exampl




все спасибо понял
P4-3.0, ASUS P5GD1, 1024MB OЗУ, GeForce 6600GT
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: объявление/описание внешней переменной

Сообщение drBatty »

Dudraug писал(а):
20.01.2008 14:04
Тогда по идее я не должен подключать main.h к funct.c а прописать в нем extern int i;
потом просто скомпилить их по отдельности, а потом слинковать?
ну или

да.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
deninok
Сообщения: 585
Статус: Программист С++
ОС: Debian GNU/Linux

Re: объявление/описание внешней переменной

Сообщение deninok »

Автору темы. Совет.
Ты, как я понял, начинающий программист. Пожелание на будущее: используй глобальные и внешние переменные (по возможности) как можно реже. Потому что если у тебя проект, где штук 70 единиц трансляции, и не один десяток переменных (а то и не одна сотня), то внешнее связывание переменных может породить весьма трудноуловимые ошибки.
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: объявление/описание внешней переменной

Сообщение drBatty »

deninok писал(а):
20.01.2008 14:20
используй глобальные и внешние переменные (по возможности) как можно реже.


+1
Ещё один совет: если уж использовать, то называть как можно более понятно(и длинно).
error_code, например.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
Dudraug
Сообщения: 313
ОС: Debian lenny/sid

Re: объявление/описание внешней переменной

Сообщение Dudraug »

Всем спасибо

Да я понимаю про глобальные переменные, но иногда с ними проще, но я сам предпочитаю их избегать.

Просто я с несколькими файлами почти не работал ( таки да совсем недавно Си учу) вот и возникли вопросы)
P4-3.0, ASUS P5GD1, 1024MB OЗУ, GeForce 6600GT
Спасибо сказали: