C глобальные переменные для всего проекта. Глобальные переменные

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

В следующей программе можно увидеть, что переменная count объявлена вне функций. Она объявляется перед функцией main(). Тем не менее, она может быть помещена в любое место до первого использования, но не внутри функции. Общепринятым является объявление глобальных переменных в начале программы.

#include

Void func1(void) , func2(void);

Int count; /* count является глобальной переменной */

Int main(void)
{
count = 100;
func1 ();
return 0; /* сообщение об удачном завершении работы */
}

Void func1 (void)
{
func2 ();
printf("счетчик %d", count); /* выведет 100 */
}

Void func2(void)
{
int count;
for(count=1; count<10; count++)
putchar(" ");
}

Рассмотрим поближе данный фрагмент программы. Следует понимать, что хотя ни main(), ни func1() не объявляют переменную count, но они оба могут ее использовать. func2() объявляет локальную переменную count. Когда func2() обращается к count, она обращается только к локальной переменной, а не к глобальной. Надо помнить, что если глобальная и локальная переменные имеют одно и то же имя, все ссылки на имя внутри функции, где объявлена локальная переменная, будут относиться к локальной переменной и не будут иметь никакого влияния на глобальную,. это очень удобно. Если забыть об этом, то может показаться, что программа работает странно, даже если все выглядит корректно.

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

  1. Они используют память в течение всего времени работы программы, а не тогда, когда они необходимы.
  2. Использование глобальных переменных вместо локальных приводит к тому, что функции становятся более частными, поскольку они зависят от переменных, определяемых снаружи.
  3. Использование большого числа глобальных переменных может вызвать ошибки в программе из-за неизвестных и нежелательных эффектов.

Одним из краеугольных камней структурных языков является разделение кода и данных. В С разделение достигается благодаря использованию локальных переменных и функций. Например, ниже показаны два способа написания mul() - простой функции, вычисляющей произведение двух целых чисел.

Два способа написания mul()
Общий Частный
int mul(int х, int у)
{
return(x*y);
}
int х, у;
int mui(void)
{
return(x*y);
}

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

Каждая переменная имеет свою область видимости, то есть такую область, в которой можно работать с переменной. За пределами этой области, о данной переменной ничего известно не будет, а значит и использовать её нельзя. Итак, переменная находится в области видимости, если к ней можно получить доступ.

Существуют локальные и глобальные переменные. Так вот, переменные, объявленные внутри функции, называются локальными. Локальные переменные имеют свои области видимости, этими областями являются функции, в которых объявлены переменные. Таким образом, в разных функциях можно использовать переменные с одинаковыми именами, что в свою очередь очень удобно. Разделение переменных на глобальные и локальные соответствует одному из главных правил программирования, а именно – принципу наименьших привилегий. То есть, переменные, объявленные внутри одной функции, должны быть доступны только для этой функции и ни чему другому, в конце концов, они создавались именно для этой функции. Глобальные переменные объявляются вне тела какой-либо функции, и поэтому область видимости таких переменных распространяется на всю программу. Обычно глобальные переменные объявляются перед главной функцией, но можно объявлять и после функции main() , но тогда данная переменная не будет доступна в функции main() .

Разработаем программу, в которой будут объявлены две переменные, локальная и глобальная, с одинаковым именем.

"stdafx.h" #include << "local variable = " << variable << endl; // печать значения содержащегося в локальной переменной example(); // запуск функции system("pause"); return 0; } void example() { cout << "global variable = " << variable << endl; // функция видит только глобальную переменную }

// код Code::Blocks

// код Dev-C++

// variables.cpp: определяет точку входа для консольного приложения. #include using namespace std; void example(); int variable = 48; // инициализация глобальной переменной int main(int argc, char* argv) { int variable = 12; // инициализация локально переменной cout << "local variable = " << variable << endl; // печать значения содержащегося в локальной переменной example(); // запуск функции return 0; } void example() { cout << "global variable = " << variable << endl; // функция видит только глобальную переменную }

В строках 8 и 12 объявлены переменные одинакового типа с одним и тем же именем variable , но переменная в строке 8 является глобальной переменной, а переменная в строке 12 — это локальная переменная. Функция example() имеет доступ только к глобальной переменной. В то время как функция main() имеет доступ как к локальной так и к глобальной переменным. Если в области видимости есть и локальная и глобальная переменные с одинаковыми именами, то при обращении к ним, будет использоваться ближайшая переменная, а это локальная переменная, это видно по результату работы программы (см. Рисунок 1).

Local variable = 12 global variable = 48

Рисунок 1 — Локальные и глобальные переменные в С++

Как мы уже сказали, функция main() имеет доступ и к глобальной переменной, но не показали, как получить этот доступ. В С++ существует такая операция, как разрешение области действия :: . Эта операция позволяет обращаться к глобальной переменной из любого места программы.» Все, что нужно сделать, так это поставить двойное двоеточие перед именем переменной. Ниже показан код, верхней программы с одним лишь изменением, и это изменение – операция разрешения доступа в строке 13 .

using namespace std; void example(); int variable = 48; // инициализация глобальной переменной int main(int argc, char* argv) { int variable = 12; // инициализация локально переменной cout << "local variable = " << ::variable << endl; // печать значения содержащегося в глобальной переменной example(); // запуск функции system("pause"); return 0; } void example() { cout << "global variable = " << variable << endl; // функция видит только глобальную переменную }

// код Code::Blocks

// код Dev-C++

// variables.cpp: определяет точку входа для консольного приложения. #include using namespace std; void example(); int variable = 48; // инициализация глобальной переменной int main(int argc, char* argv) { int variable = 12; // инициализация локально переменной cout << "local variable = " << ::variable << endl; // печать значения содержащегося в глобальной переменной example(); // запуск функции return 0; } void example() { cout << "global variable = " << variable << endl; // функция видит только глобальную переменную }

Операция разрешения области действия ставится перед именем глобальной переменной, и даже, если есть локальная переменная с таким же именем, программа будет работать со значением, содержащимся в глобальной переменной. Результат работы программы (см. Рисунок 2).

Local variable = 48 global variable = 48

Рисунок 2 — Локальные и глобальные переменные в С++

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

Локальные и глобальные переменные

Время жизни объекта может быть глобальным и локальным.

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

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

Пример на Си

1
2
3
4
5
6
7
8
9
10
11
12
13
14

#include
void autofunc(void )
{
int k = 1; // локальный объект
printf(" \n k = %d " , k);
k = k + 1;
}
int main()
{
for (int i = 0; i <= 5; i++)
autofunc();
getchar();
return 0;
}

Область видимости локальной переменной k - функция autofunc() . Каждый раз при входе в функцию с идентификатором k ассоциируется некоторая ячейка памяти, в которую помещается значение равное 1.

Та же программа, но с использованием глобального объекта

1
2
3
4
5
6
7
8
9
10
11
12
13
14

#include
int k = 1; // глобальный объект
void autofunc(void )
{
printf(" \n k = %d " , k);
k = k + 1;
}
int main()
{
for (int i = 0; i <= 5; i++) // область видимости i - цикл
autofunc();
getchar();
return 0;
}


Результат выполнения программы


С помощью глобальных переменных можно организовать обмен информацией между функциями. При этом вызываемая функция не будет принимать значения глобальных переменных в качестве формальных аргументов. Однако в этом случае существует опасность случайного изменения глобальных объектов другими функциями.

Пример на Си

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18


#include
int x, y, z; // глобальные переменные
void sum(void )
{
z = x + y;
}
int main()
{
printf("x= " );
scanf("%d" , &x);
printf("y= " );
scanf("%d" , &y);
sum();
printf("z= %d" , z);
getchar(); getchar();
return 0;
}


Результат выполнения

Модификация объектов

Модификация или видоизменение объектов в языке Си применяется для того, чтобы изменить диапазон значений или область действия объекта. Ключевые слова, которые применяются для модификации, называются модификаторами .


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


Модификатор extern предназначен для использования в данном программном модуле объекта, который объявлен в другом программном модуле.

Файл 1 Файл 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

#define _CRT_SECURE_NO_WARNINGS
#include
int x, y, z;
extern void func(void );
int main()
{
printf("x= " );
scanf("%d" , &x);
printf("y= " );
scanf("%d" , &y);
func();
printf("z= %d" , z);
getchar(); getchar();
return 0;
}

1
2
3
4
5

extern int x, y, z;
void func(void )
{
z = x + y;
}

Пример окна проекта, состоящего из двух файлов



Модификатор static позволяет связать с идентификатором фиксированный адрес (ячейку памяти). Если объект расположен по некоторому фиксированному адресу, то он называется статическим .

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

Пример на Си

1
2
3
4
5
6
7
8
9
10
11
12
13
14

#include
void autofunc(void )
{
static int k = 1; // статический объект
printf(" \n k = %d " , k);
k = k + 1;
}
int main()
{
for (int i = 0; i <= 5; i++)
autofunc();
getchar();
return 0;
}


Переменная k в функции autofunc() зафиксирована в оперативной памяти. Инициализация k проводится только один раз - при первом вызове функции. При повторном обращении к функции autofunc() инициализация переменной k не будет производиться. Значение переменной k и ее адрес сохраняются в оперативной памяти, однако эта переменная не будет доступна из других функций.

Результат выполнения программы


Модификатор register предназначен для того, чтобы поместить переменную в один из регистров общего назначения центрального процессора при наличии свободного регистра. Благодаря этому повышается скорость работы с данными. Это необходимо для создания управляющих программ, где требуется высокая скорость обработки данных.