2013-07-12 2 views
0

Я пишу общую/динамическую библиотеку (https://github.com/zsawyer/mumble-LinkAPI).Оптимизация C (C89) с передачей кодов ошибок

Для этого я предоставил некоторые базовые элементы доступа (получить, установить и обновить) для данных в структуре разделяемой памяти (не может быть изменен, поскольку он определяется извне). Существует множество аксессуаров, которые предоставит моя библиотека. Методы Getter и Setter в порядке, imo, но мои функции дают мне проблемы. Они все в значительной степени будут выглядеть одинаково - я чувствую много избыточности кода.

Примечание: Я хочу придерживаться C89! То есть: I не хотите использовать C++, ни C99, C11.

Обновление name является примером для почти всех других функций обновления (аргументы будут различаться):

ErrorCode updateName(wchar_t name[MAX_NAME_LENGTH]) { 
    ErrorCode err = setName(name); 
    if (err != ERROR_CODE_NO_ERROR) { 
     return err; 
    } 
    return commit(); 
} 

Коды ошибок определены в перечислении:

/** 
* error codes hinting at the root cause of a failure 
*/ 
typedef enum { 
    /** no error */ 
    ERROR_CODE_NO_ERROR = 0, 
    /** win32 specific: OpenFileMappingW failed to return a handle */ 
    ERROR_CODE_WIN32_NO_HANDLE = 1, 
    /** win32 specific: MapViewOfFile failed to return a structure */ 
    ERROR_CODE_WIN32_NO_STRUCTURE = 2, 
    /** unix specific: shm_open returned a negative integer */ 
    ERROR_CODE_UNIX_NO_HANDLE = 3, 
    /** unix specific: mmap failed to return a structure */ 
    ERROR_CODE_UNIX_NO_STRUCTURE = 4, 
    /** shared memory was not initialized */ 
    ERROR_CODE_NO_MEMORY_WAS_INITIALIZED = 5 
} ErrorCode; 

Я хочу передать первоначальную ошибку кода до вызывающей функции библиотеки, избегая при этом записи одной и той же функции x-раз с другой функцией и параметром setXxx. Я чувствую, что должен быть более простой способ.

Вопрос: Как я могу переписать обновления функции передать ErrorCode и еще уменьшить избыточность кода и сделать функцию более удобным для чтения/короче?


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

ответ

1

Как об определении функции

int commit_if_ok(int prev_error_code) 
{ 
    if (prev_error_code != ERROR_CODE_NO_ERROR) 
    return prev_error_code; 
    else 
    return commit(); 
} 

и использовать его как:

ErrorCode updateName(wchar_t name[MAX_NAME_LENGTH]) 
{ 
    return commit_if_ok(setName(name)); 
} 

Обратите внимание, что commit_if_ok может быть встроенная функция, если ваш конкретный компилятор директивы, чтобы позволить, что (многие старые компиляторы дон 't, но некоторые делают), но это не должно быть макросом, потому что он дважды использует свой аргумент.

+0

Кажется немного странным передавать код ошибки в качестве аргумента, но определенно лучше, чем у меня сейчас. И спасибо за объяснение, почему бы не использовать макрос в этом случае. – zsawyer

+0

Я часто желал, чтобы 'x || y' был определен как 'x? y: x', но с 'x' оценивается ровно один раз, а' x && y' был определен как 'x? y: 0'. Хотя эти операторы дают точное значение 1 во всех ненулевых случаях, иногда полезно, иногда это неудобно (особенно в случае '||'), часто генерирует бесполезный код и редко помогает. – supercat

Смежные вопросы