Как лучше всего управлять ресурсами для программы C. Должен ли я использовать вложенную структуру if или мне следует использовать операторы goto?
Я знаю, что существует множество табу на инструкции goto. Однако я считаю это оправданным для очистки местных ресурсов. Я предоставил два образца. Один сравнивает вложенную структуру if, а другой использует операторы goto. Я лично считаю, что операторы goto упрощают чтение кода. Для тех, кто может возразить, что вложенное if предлагает лучшую структуру, представьте, что тип данных был чем-то другим, кроме char *, например дескриптором Windows. Я чувствую, что структура вложенного if выйдет из-под контроля с серией CreateFile или любую другую функцию, которая принимает большое количество параметров.
В этой статье показано, что локальные операторы goto создают RAII для кода C. Код аккуратный, за ним легко следить. Представьте себе это как серию вложенных операторов if.
Я понимаю, что goto является табу на многих других языках, потому что существуют другие механизмы управления, такие как try / catch и т. Д., Однако в C это кажется уместным.
#include <stdlib.h>
#define STRING_MAX 10
void gotoExample()
{
char *string1, *string2, *string3, *string4, *string5;
if ( !(string1 = (char*) calloc(STRING_MAX, sizeof(char))) )
goto gotoExample_string1;
if ( !(string2 = (char*) calloc(STRING_MAX, sizeof(char))) )
goto gotoExample_string2;
if ( !(string3 = (char*) calloc(STRING_MAX, sizeof(char))) )
goto gotoExample_string3;
if ( !(string4 = (char*) calloc(STRING_MAX, sizeof(char))) )
goto gotoExample_string4;
if ( !(string5 = (char*) calloc(STRING_MAX, sizeof(char))) )
goto gotoExample_string5;
//important code goes here
gotoExample_string5:
free(string4);
gotoExample_string4:
free(string3);
gotoExample_string3:
free(string2);
gotoExample_string2:
free(string1);
gotoExample_string1:
}
void nestedIfExample()
{
char *string1, *string2, *string3, *string4, *string5;
if (string1 = (char*) calloc(STRING_MAX, sizeof(char)))
{
if (string2 = (char*) calloc(STRING_MAX, sizeof(char)))
{
if (string3 = (char*) calloc(STRING_MAX, sizeof(char)))
{
if (string4 = (char*) calloc(STRING_MAX, sizeof(char)))
{
if (string5 = (char*) calloc(STRING_MAX, sizeof(char)))
{
//important code here
free(string5);
}
free(string4);
}
free(string3);
}
free(string2);
}
free(string1);
}
}
int main(int argc, char* argv[])
{
nestedIfExample();
gotoExample();
return 0;
}
Я также хотел бы процитировать Линуса Торвальдса о выражениях goto внутри ядра Linux а>.
А иногда структура плохая и мешает, и использование «goto» намного яснее.
Например, довольно часто используются условные выражения, КОТОРЫЕ НЕ ВСТАВЛЯЮТСЯ.
В этом случае у вас есть две возможности
используйте goto и будьте счастливы, так как он не требует вложенности
Это делает код более читабельным, поскольку код просто выполняет то, что алгоритм должен делать.
продублируйте код и перепишите его во вложенной форме, чтобы вы могли
использовать структурированные переходы.Это часто делает код намного МЕНЬШЕ читабельным, сложным в обслуживании и большим.
Язык Паскаль - яркий пример последней проблемы. Поскольку в нем нет оператора break, циклы в (традиционном) Паскале часто выглядят как полное дерьмо, потому что вам нужно добавить совершенно произвольную логику, чтобы сказать: «Я закончил».
Подходит ли goto для управления ресурсами? Следует ли мне использовать вложенные операторы if или есть способ лучше?
Обновление: Примеры хороших Gotos на C < / а>
freeбезвредна (nop). В этом случае заверение васfreeтолько в успешном распределении приводит к (значительной) дополнительной работе. - person Jerry Coffin   schedule 11.11.2010