холи.., а, у меня для этого даже картинка есть (многие с ней уже знакомы, хе хе) языкохоливар! что-то мы про него в самом деле в последнее время забыли) давайте уж тогда про ООП сразу, вот я ООП люто презираю, потому что он абстрагирует, а это недопустимо, когда речь идёт о чистой логике! )
osox правильный вариант 1 вариант 2 это то во что преобразует компилятор и преобразиться в asm коде вариант 3 дурдом 4 - это не С код, это идиома M$
do { } while(0); вполне нормальная конструкция, только глубину вложенности повышает, однако чаще всего не очень сильно мешает.
Вложенные ифы, кстати, вполне приемлимы, если вызовов функций до 4х штук. Ну а так обычно я юзаю 2 или 4. (вариант 1 - бред) GoldFinch за такие посты надо бить по еб.. лицу
ну есть же 2 схемы работы. SEME и SESE. Single Enter Single (Multiply) Exit. У каждого подхода свои плюсы и минусы.
вообщем так удобно получилось Код (Text): retcode ubzd4guwedudy(argtype this) { file_t file = NULL; thread_t thread = NULL; map_t map = NULL; retcode retval; file = openfile... EXIT_ON_TRUE(!file, ERROR_FILE_NOT_FOUND); thread = openthread... EXIT_ON_TRUE(!thread, ERROR_ACCESS_DENIED); map = openmap... EXIT_ON_TRUE(!map, ERROR_NOT_ENOUGH_MEMORY); retval = ERROR_SUCCESS; ...processing... Exit: CLEANUP(closefile, file); CLEANUP(closethread, thread); CLEANUP(closemap, map); return retval; } а вообще вот еще макросов для разных ситуаций написал Код (Text): #define FINALLY_ON_TRUE(expr) \ do { if (expr) { __leave; } } while (0) #define FINALLY_VAL_ON_TRUE(expr, retvalue) \ do { if (expr) { retval = retvalue; __leave; } } while (0) #define EXIT_ON_TRUE(expr) \ do { if (expr) { goto Exit; } } while (0) #define EXIT_VAL_ON_TRUE(expr, retvalue) \ do { if (expr) { retval = retvalue; goto Exit; } } while (0) /* * RESOURCE_NOT_RESERVED * jump to cleanup before allocating resource */ #define RESOURCE_NOT_RESERVED 0x20000005 #define CLEANUP_RET(pfn, val) ( \ (val) ? \ (intptr_t)(pfn)(val) : \ RESOURCE_NOT_RESERVED ) #define CLEANUP(pfn, val) ((void)( \ (val) ? (pfn)(val) : 0 )) #define CLEANUP_VAL(pfn, val1, val2) ((void)( \ ((val1) != (val2)) ? (pfn)(val1) : 0 )) #define CLEANUP_ON_TRUE(pfn, val, flag) ((void)( \ ((val) && (flag)) ? (pfn)(val) : 0 )) #define CLEANUP_ON_TRUE_IF(pfn, val1, val2, expr) ((void)( \ ((val1) && (val2) && (expr)) ? (pfn)(val2) : 0 ))
Great за какие? про то что на Си норм люди не пишут? так Си полностью входит в С++, Си устарел, он не развивается т.к. нафиг никому не нужен, последний стандарт вышел 11лет назад, и его до сих под мало кто поддерживает, т.к. все забили на Си да и развивать там нечего - все уже развито в С++ Си не отвечает требованиям предъявляемым к современным промышленным языкам, by design единственный смысл юзать Си - юзать его там, где нет ничего лучше, например для МК для которых нет компилятора С++ или других языков собственно это тема - причина того что Си устаревший язык. В других языках такой проблемы нет, юзать goto для разруливания ошибок, или нет
n0name мне она поэтому и не нравится что на пустом месте растет уровень вложенности это какое то готофобство уже получается лучше уж goto чем это хотя кому как найдутся и сторонники иного мнения ))
osox Вложенность видно сразу, а метку нет. Что касается остальных вариантов - мне наиболее симпатичен третий, поскольку логику программы проще понять предполагая положительный результат вызова ф-ций. И пофик сколько уровней вложенности. Иначе, вспоминается комичный вариант объяснения прохожему как пройти до места назначения: там увидишь поворот направо, туда не ходи, потом слева будет улица, которая ведет на рынок, тебе туда тоже не нужно, потом еще будет поворот, если туда пойти, то увидишь еще что-то, но тебе тоже не туда.. вместо того, чтобы просто сказать - иди прямо.