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 */
}
Другие вопросы по тегам