C: Сгенерировать ошибку при проверке параметров или позволить ей попасть в вентилятор?
У меня есть простой дизайн (?) Вопрос.
Я пишу простую программу, у которой есть пара функций, которые выглядят следующим образом.
float foo (float* m,size_t n){
float result;
//do some calculations, for example a sum
return result / n;
}
У меня есть пара вопросов по этому поводу, и я не собираюсь открывать какую-то священную войну.
Должен ли я добавить проверку работоспособности на n
? Если так, как я должен сообщить звонящему?
возврате -1
выглядит странно на поплавках;
float foo(float *m,size_t n){
if (n == 0) return -1f
...
}
Мой другой вариант - это параметр out
float foo(float *m,size_t n, int *error){
if (n==0){
*error = 1;
return 0f;
}
...
}
Обновить
Это что-то вроде игрушечной программы, просто пытаюсь попрактиковаться. Вопрос превосходит этот факт. Может быть, я должен перефразировать "как обрабатывать ошибки без (ООП) исключений".
Также рассматриваю тестирование n
перед тем, как сделать звонок, но не так сильно.
Какие-нибудь мысли? Заранее спасибо.
4 ответа
Я полагаю, ваш out parameter
вариант хороший. Но я думаю, что было бы лучше, если бы все было иначе. Используйте параметр out, чтобы получить результат и возвращаемое значение, чтобы обозначить статус вызова. Как это
int foo(float *m, size_t n, float* result)
{
if(someFailureCondition)
return ERROR; // ERROR being an error integer
// else
// do some calculation
// set your result
return NO_ERROR; // NO_ERROR being an integer
}
Редактировать: возвращаемое значение может быть более подробным, чтобы обозначить текущее состояние параметра out. Смотрите комментарий Джеймслина!
Если -1 не будет возвращен функцией в любом случае, непременно верните -1. Но если передача n=0 не нарушит функцию, то в этом нет необходимости. Я предполагаю, что n - это размер массива m.
Обработка ошибок является вопросом предпочтения. OpenGL обрабатывает ошибки, возвращая код ошибки (-1 или иным образом) при сбое функции. Код ошибки возвращается через вызов GetLastError() (или что-то в этом роде). Это кажется идеальным решением для обработки ошибок.
Существуют специальные значения с плавающей запятой, которые вы можете использовать, если хотите - например, если ваша реализация с плавающей запятой поддерживает тихие NaN (Not-a-Number), тогда вы можете использовать NAN
макрос из math.h
:
#include <math.h>
float foo(float *m,size_t n)
{
if (n == 0) return NAN;
...
}
Вы должны сообщить вызывающим сторонам, какова семантика вашей функции, четко документируя ваш код.
Какой контракт на вашу функцию? Если вызывающие абоненты обязаны не передавать 0 для n
, тогда это должно быть объяснено, и функция должна использовать assert
чтобы убедиться, что эти требования выполнены. Логические ошибки должны быть обнаружены на ранней стадии, и эти сбои должны быть как можно более зрелищными.
Теперь, если вы пишете код для библиотеки, которая будет использоваться другими разработчиками и обеспокоена тем, что люди будут компилировать assert
отключить, то разумно объединить это с более мягким режимом отказа, который всегда включен:
if (n == 0)
{
assert(0);
return NAN; /* Or return some error code */
}