C - структура программы (без глобальных переменных, включений и т. Д.)
Я использую C (не C++), и я не уверен, как избежать использования глобальных переменных.
Я довольно неплохо разбираюсь в C, его синтаксисе и способах написания базового приложения, но я не уверен в правильном способе структурирования программы.
Как действительно большие приложения избегают использования глобальных переменных? Я почти уверен, что всегда должно быть хоть что-то, но для больших игр и других приложений, написанных на C, какой лучший способ сделать это?
Есть ли какое-нибудь хорошее программное обеспечение с открытым исходным кодом, написанное строго на C, на которое я мог бы посмотреть? Я не могу думать ни о чем из головы, большинство из них, кажется, в C++.
Благодарю.
редактировать
Вот пример, где я бы использовал глобальную переменную в простом приложении перехвата API, которое является просто DLL внутри другого процесса.
Это приложение, в частности, перехватывает функции API, используемые в другом приложении. Это делается с помощью WriteProcessMemory, чтобы перезаписать вызов оригинала и сделать вместо этого вызов моей DLL.
Однако при отключении функции API я должен записать исходную память / машинный код.
Итак, мне нужно поддерживать простой байтовый массив для этого машинного кода, по одному для каждой подключенной функции API, и их много.
// Global variable to store original assembly code (6 bytes)
BYTE g_MessageBoxA[6];
// Hook the API function
HookAPIFunction ( "user32.dll", "MessageBoxA", MyNewFunction, g_MessageBoxA );
// Later on, unhook the function
UnHookAPIFunction ( "user32.dll", "MessageBoxA", g_MessageBoxA );
Извините, если это сбивает с толку.
6 ответов
"Как действительно большие приложения избегают использования глобальных переменных?"
Используйте статические переменные. Если функция должна что-то запомнить между вызовами, используйте это в сравнении с глобальными переменными. Пример:
int running_total (int num) { static int sum = 0; sum += num; return sum; }
Передача данных через параметры, так что значение определяется в одном месте, может быть
main()
и перешел туда, где это необходимо.Если ничего не помогает, используйте глобальный подход, но постарайтесь смягчить потенциальные проблемы.
- Как минимум, используйте соглашения об именах, чтобы минимизировать потенциальные конфликты. НАПРИМЕР:
Gbl_MyApp_DeveloperName
, Таким образом, все глобальные переменные будут начинаться сGbl_MyApp_
часть - где "MyApp" было чем-то описательным для вашего приложения. - Попробуйте сгруппировать функции по назначению, чтобы все, что нужно для данного глобального объекта, находилось в одном файле (в пределах разумного). Тогда глобальные переменные могут быть определены и ограничены этим файлом (остерегайтесь
extern
ключевое слово).
- Как минимум, используйте соглашения об именах, чтобы минимизировать потенциальные конфликты. НАПРИМЕР:
Это просто - просто не используйте их. создайте то, что будет иметь глобальные переменные в вашей функции main(), а затем передайте их оттуда в качестве параметров функциям, которые в них нуждаются.
Есть несколько допустимых вариантов использования глобальных переменных. В школах начали учить, что они злые, чтобы программисты не ленились и не злоупотребляли ими. Если вы уверены, что данные действительно нужны глобально, используйте их. Учитывая, что вы беспокоитесь о том, чтобы хорошо выполнять свою работу, я не думаю, что вы слишком далеко ошибетесь, используя собственное суждение.
Лучшим рекомендуемым программным обеспечением с открытым исходным кодом для изучения C в моем колледже была Linux, так что вы можете получить примеры из их источников.
Я думаю так же, глобальные переменные плохие, снижают читаемость и увеличивают вероятность ошибок и других проблем.
Я объясню мой пример. У меня есть main(), который делает несколько вещей. Большая часть действия происходит от таймеров и внешних прерываний. Это функции без параметров, из-за платформы, которую я использую, 32-битный микроконтроллер. Я не могу передать параметры и, кроме того, эти прерывания и таймеры являются асинхронными. Самый простой способ - глобальный, представьте, прерывает заполнение буфера, этот буфер анализируется в таймере, а анализируемая информация используется, сохраняется, отправляется в другие таймеры. Хорошо, я могу установить флаг прерывания и обработать его в основной функции, но при выполнении критически важного программного обеспечения это плохая идея.
Это единственный вид глобальной переменной, который не заставляет меня чувствовать себя плохо;-)
Глобальные переменные почти неизбежны. Тем не менее, они часто злоупотребляют. Они не являются заменой для передачи правильных параметров и проектирования правильных структур данных.
Каждый раз, когда вам нужна глобальная переменная, подумайте: а если мне понадобится еще одна такая?