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 ответов

Решение

"Как действительно большие приложения избегают использования глобальных переменных?"

  1. Используйте статические переменные. Если функция должна что-то запомнить между вызовами, используйте это в сравнении с глобальными переменными. Пример:

    int running_total (int num) {
        static int sum  = 0;
        sum             += num;
        return sum;
    }
    
  2. Передача данных через параметры, так что значение определяется в одном месте, может быть main() и перешел туда, где это необходимо.

  3. Если ничего не помогает, используйте глобальный подход, но постарайтесь смягчить потенциальные проблемы.

    1. Как минимум, используйте соглашения об именах, чтобы минимизировать потенциальные конфликты. НАПРИМЕР: Gbl_MyApp_DeveloperName, Таким образом, все глобальные переменные будут начинаться с Gbl_MyApp_ часть - где "MyApp" было чем-то описательным для вашего приложения.
    2. Попробуйте сгруппировать функции по назначению, чтобы все, что нужно для данного глобального объекта, находилось в одном файле (в пределах разумного). Тогда глобальные переменные могут быть определены и ограничены этим файлом (остерегайтесь extern ключевое слово).

Это просто - просто не используйте их. создайте то, что будет иметь глобальные переменные в вашей функции main(), а затем передайте их оттуда в качестве параметров функциям, которые в них нуждаются.

Есть несколько допустимых вариантов использования глобальных переменных. В школах начали учить, что они злые, чтобы программисты не ленились и не злоупотребляли ими. Если вы уверены, что данные действительно нужны глобально, используйте их. Учитывая, что вы беспокоитесь о том, чтобы хорошо выполнять свою работу, я не думаю, что вы слишком далеко ошибетесь, используя собственное суждение.

Лучшим рекомендуемым программным обеспечением с открытым исходным кодом для изучения C в моем колледже была Linux, так что вы можете получить примеры из их источников.

Я думаю так же, глобальные переменные плохие, снижают читаемость и увеличивают вероятность ошибок и других проблем.

Я объясню мой пример. У меня есть main(), который делает несколько вещей. Большая часть действия происходит от таймеров и внешних прерываний. Это функции без параметров, из-за платформы, которую я использую, 32-битный микроконтроллер. Я не могу передать параметры и, кроме того, эти прерывания и таймеры являются асинхронными. Самый простой способ - глобальный, представьте, прерывает заполнение буфера, этот буфер анализируется в таймере, а анализируемая информация используется, сохраняется, отправляется в другие таймеры. Хорошо, я могу установить флаг прерывания и обработать его в основной функции, но при выполнении критически важного программного обеспечения это плохая идея.

Это единственный вид глобальной переменной, который не заставляет меня чувствовать себя плохо;-)

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

Каждый раз, когда вам нужна глобальная переменная, подумайте: а если мне понадобится еще одна такая?

Другие вопросы по тегам