Переменные, используемые в программе, могут быть не только глобальными, локальными или статическими, но также могут представлять внешние объекты. Такие объекты определены в каком-то внешнем файле. Кроме того, функции также могут внешними по отношению к другим функциям, то есть также могут быть определены в других файлах. И в этом случае встает вопрос организации взаимодействия между ними. Рассмотрим пример такого взаимодействия.
Пусть у нас в программе будет два файла: главный файл app.c и вспомогательный файл main.c.
Пусть файл main.c будет содержать следующий код:
#include <stdio.h> char message[] = "Hello METANIT.COM"; void print() { printf("Hello from extern function\n"); } int sum(int x, int y) { return x + y; }
Здесь определена одна переменная - message
и дву функции - print()
и sum()
.
используем этот функционал в файле app.c, который будет представлять главный файл программы:
#include <stdio.h> extern char message[]; // переменная message из файла main.c void print(void); // функция print из main.c int sum(int, int); // функция sum из main.c int main(void) { // выводим на консоль внешнюю переменную message printf("%s \n", message); // вызываем внешнюю функцию print print(); // вызываем другую внешнюю функцию - sum printf("4 + 5 = %d \n", sum(5, 4)); return 0; }
Если переменная определена во внешнем файле, то перед ее использованием должно идти ее описание с
ключевым словом extern. В частности, в файле main.c определена переменная message
. Чтобы к ней обращаться,
в файл app.c надо поместить ее описание с ключевым словом extern:
extern char message[];
Описание переменной в принципе совпадает с ее определением, только при описании ей нельзя присваивать какое-либо значение.
Если мы хотим использовать внешние функции, то перед их использованием надо определить их прототип. Так, в файле main.c определены
функции print()
и sum()
, поэтому в файле app.c перед вызовом этих функции помещается их прототип:
void print(void); // функция print из main.c int sum(int, int); // функция sum из main.c
То же самое касается использования любых других переменных и функций, которые определены во внешних файлах.
При компиляции через GCC компилятору надо последовательно через пробел передать имена файлов:
gcc app.c main.c -o app.exe
Здесь файлы app.c и main.c будут компилироваться в один файл app.exe.
В некоторых средах разработки (например, в Visual Studio) среда разработки автоматически скомпилирует оба файла в одну программу.
По умолчанию любая глобальная переменная или константа или функция из одного файла доступна в другом файла при совместной компиляции, как в примере выше. Однако иногда возникает необходимость, наоборот, скрыть переменную или функцию, чтобы внешние файлы не могли их использовать. В этом случае к подобным переменным и функциям можно применить оператор static, сделав их статическими. Например, определим следующий файл main.c:
#include <stdio.h> static char message[] = "Hello METANIT.COM"; static void print() { printf("%s\n", message); } void hello() { print(); }
Теперь ни переменная message
, ни функция print()
не доступны из внешних файлов, потому что они определены как статические. А вот функция hello()
доступна и только ее мы можем использовать в других файлах, например, в файле app.c:
#include <stdio.h> //extern char message[]; - переменная message из файла main.c недоступна // void print(void); - функция print из main.c недоступна void hello(void); // функция hello из main.c доступна int main(void) { // вызываем другую внешнюю функцию - hello hello(); return 0; }