#48. Локальные и глобальные переменные | Язык C для начинающих
HTML-код
- Опубликовано: 18 окт 2024
- Практический курс по C/C++: stepik.org/cou...
Телеграм-канал: t.me/java_and_c
Инфо-сайт: proproprogs.ru...
Что из себя представляют локальные и глобальные переменные. Где и как они хранятся. Какие ограничения имеют.
спасибо, было интересно. Потихоньку все становится на свои места.
Спасибо. Все понятно и доступно.
Применение глобальных переменных допустимо, если это уникальные объекты и есть много функций, которые работают именно с этим объектом.. Например, массив представляющий собой игровое поле, причем только одно. И все функции только с этим полем работают - одна его очищает, другая там что-то расставляет, третья ищет и т.д. В этом случае удобно вместо передачи в каждую функцию параметра, означающего это поле, просто использовать его по глобальному идентификатору.
И такие глобальные переменные должны иметь длинное осмысленное имя, чтобы сразу было понятно его назначение, и не было конфликта с какой-то локальной переменой. Т.е. называть нужно не А,S, x, а например main_game_board.
Более точно "область видимости" - часть программы, в пределах которой идентификатор некой сущности (переменной, константы, функции, типа и пр.) остаётся связанным с этой сущностью, то есть через этот идентификатор можно обратиться к этой переменной, константе и пр. За пределами области видимости тот же самый идентификатор может быть не связан ни с чем (имя не имеет смысла) или связан с чем-то другим (эта другая одноименная сущность экранирует, "заслоняет собой" старую).
И есть еще "областью существования ", т.е. промежуток между созданием чего-то (выделением для переменной памяти) и уничтожением (освобождением памяти). Область видимости и существования - не одно и то же. Переменная может существовать (занимать память и хранить значение), но быть недоступной, потому что заслонена какой-то одноименной сущностью.
Спасибо за урок. Это курс по теории. А что порекомендуете по практике? У вас нет отдельного курса?
пока только теория
По каким языка программирования вы преподаёт курсы?
И где можно их найти?
Сергей, как ты думаешь, уместно ли делать ассемблерные вставки из компиляции программы, для лучшей наглядности? (как, например, выделяется память для локальных переменных в стеке, пролог и эпилог функций и т.д.)? Лайк за работу!!!
Только ради наглядности, думаю, не особо нужно. Их добавляют только если нужно реализовать что то особенное с полным контролем за процессом выполнения машинного кода. Во всех остальных случаях компилятор языка Си прекрасно справляется с переводом программы в машинные коды без каких-либо вставок.
спасибо
Спасибо за видео) А сколько составляет объем стека? Встречал инфу, что в районе 1МБ, это правда?)
Вроде в современных ПК порядка 8 Мб, но это можно настраивать в настройках компилятора (хотя, как правило, не требуется).
А с точки зрения производительности (если программа выполняет вечный цикл, в котором вызываются функция, где создаётся переменная) использование глобальных переменных может быть оправдано?
Надо смотреть, возможно компилятор это оптимизирует и даже функцию вызывать не будет, а просто подставит ее тело в цикл ))
Не представляю как строить программы без глобальных переменных содержащих значения о состоянии системы
Сергей, помогите, пожалуйста разобраться.
То, что вы называете стековым фреймом (stack frame), судя по различным источникам, должно называться стеком вызовов (call stack). Стек вызовов относится ко всей программе, в то время как стековый фрейм относится только к конкретной функции. Это напрямую следует даже из статьи на википедии:
en.wikipedia.org/wiki/Call_stack#STACK-FRAME
Вы говорите о стековом фрейме как о стеке вызовов сразу в нескольких видео данного плейлиста, поэтому я счел возможным задать вопрос напрямую: это я что-то не так понял из ваших слов, или вы что-то другое имели в виду?
Это ни в коем случае не критика и не замечание, просто хочу разобраться до конца.
Спасибо.
да, вы правы, стековый фрейм терминологически относится к одному вызову функции, то что у меня - это объединение стека вызовов и фреймового стека, спасибо!
Не соглашусь с некоторыми утверждениями. У переменных объявленных внутри тела функции, область видимости не "в пределах функции", а "в пределах блока" (единственными идетификаторами, которые обладают областью видимости в пределах функции являются метки от goto). Так же эти переменные "создаются" не при входе в функцию, а при входе в блок. Другое дело, что у тела функции есть свой блок и переменные, объявленные в этом блоке будут "созданы" при входе в него, т. е. при входе в функцию, но если, например, в функции имеются вложенные блоки (например цикл for), то переменные объявленные внутри такого вложенного блока будут создаваться и уничтожаться при входе в этот вложенный блок и выходе из этого блока соответственно, а не функции, и не будут видны вне этого вложенного блока (а вот на метку goto можно свободно прыгнуть из такого вложенного блока в любой другой в пределах функции, пожтому метки goto имеют область видимости в пределах функции).
можно просто объявлять блок, без циклов и функций:
{
long x = 0;
}
Все эти детали дальше. Сразу грузить всей этой информацией не стал в одном занятии.
В случае с микроконтроллерами без использования глобальных переменных просто не обойтись (если конечно используются обработчики прерываний).
да, там есть такое, согласен!
А то что выделяемая операционной системой память, забита нулями, связанно с защитой памяти, то есть там может быть конфиденциальная информация, которая не должна быть доступна другой программе, поэтому перед предоставлением этого участка памяти он очищается
Нет, конечно )) Просто так решили разработчики компилятора: один раз при загрузке программы забить память нулями почти ничего не стоит, в отличие от локальных переменных, которые постоянно то размещаются в стеке, то убираются из него. Там эта операция более затратна.
@@selfedu_rus Я в данном случае не имел ввиду разграничение доступа к памяти, а в ядре операционной системы точно есть очистка освобождаемых областей оперативной памяти, именно с такой целью
@@selfedu_rus функция get_zeroed_page (/mm/page_alloc.c) в ядре linux делает это, но, честно говоря, как там у вас в windows и visual studio, я не знаю:)