ничего не возвращать из непустой функции в C - PullRequest
4 голосов
/ 12 июля 2010

что считается лучшей практикой в ​​следующем фрагменте:

int foo(struct data *bar, struct info bla) {
    if (!bar) {
        bla->status = 0;
        return;
    }
    ...
}

на самом деле работает нормально. но я чувствую себя неловко, когда gcc дает мне предупреждение.


вот фактический код:

static int pop(struct stack **stack, struct info *info) {
        int ret;
        struct stack *tmp;

        if (!*stack) {
                info->error = 0;
                return;
        }

        ret = (*stack)->data;
        tmp = *stack;
        *stack = (*stack)->next;
        free(tmp);

        return ret;
}

Ответы [ 8 ]

12 голосов
/ 12 июля 2010

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

Классический способ это вернутьзначение через параметр указателя, с фактической функцией, возвращающей статус:

int f( int * p ) {
   if ( bad ) {
       return 0;   // fail indicator
   }
   else {
      * p = 42;    // integer return value
      return 1;    // success indicator
   }
}

Редактировать: В размещенном вами коде вы манипулируете стеком.Выгрузка пустого стека - неопределенное поведение для всех стеков, которые я знаю, так что вы можете просто вернуть любое целое число, которое вам по вкусу (я бы вернул 0), и задокументировать поведение.

6 голосов
/ 12 июля 2010

Поведение не определено, и предупреждение есть по уважительной причине!Вернуть значение или изменить функцию на void.

1 голос
/ 12 июля 2010

В предположении, что возвращаемое значение не используется для этого конкретного случая , просто верните 0. Если используется возвращаемое значение, то в вашей программной логике есть серьезный недостаток, который необходимо исправить первый.

0 голосов
/ 12 июля 2010

Поскольку вы используете info->error, чтобы сказать, если функция не выполнена или нет, вы можете вернуть все, что захотите, так как вызывающая сторона должна игнорировать возвращаемое значение. Таким образом, вы можете отключить предупреждение с помощью return -1, return 0, return MAGIC_NUMBER ... ...

В целом, однако, функции закодированы «противоположным образом»: возвращаемое значение говорит, была ли функция выполнена успешно или нет. Если все возвращаемые значения int являются хорошими, вы можете написать функцию так, чтобы она возвращала сбой или успех, и при успешном завершении вы заполняете данные. В вашем случае ваша информационная структура может содержать int data, или вы можете добавить еще один аргумент в функцию.

Таким образом, вызывающая сторона может сделать что-то вроде

if ( pop(stack, info) == SUCCESS ) {
  // ...
  printf("%d\n", info->data);
} else { /* failure */
  // info->data holds no data, but info->error could be an error code, e.g.
  fprintf(stderr, "can't pop: %s\n", error_msg[info->error]);
}

Использование в вашем случае менее интуитивно понятно:

data = pop(stack, info);
if (info->error != ERROR) {
  // data is valid
} else {
  // data is garbage and we have to say an error occurred.
}

Кстати, вы не устанавливаете info->error на что-то другое, равное 0, поэтому ваш код потенциально содержит ошибки; например,

  info->error = 0;
  data = pop(stack, info);

всегда будет вызывать ошибку, даже если на самом деле стек в порядке и данные верны.

0 голосов
/ 12 июля 2010

Я бы рассмотрел добавление третьего параметра, который на самом деле был бы «возвращаемым значением», и вместо того, чтобы возвращать результат функции, просто вернуть ее статус, который может быть, например, enum (и вы могли бы иметь « STATUS_OK "," STATUS_FAIL "," STATUS_NO_RESULT "и т. Д.).

Это будет понятно для любого, кто использует вашу функцию и в то же время обеспечивает желаемое поведение (т. Е. Отказ от возврата значения будет означать, что вы не трогаете третий параметр и не возвращаете «STATUS_NO_RESULT»).

0 голосов
/ 12 июля 2010
int main(void)
{
    printf("hello world\n");
}

возвращает 10. Оболочка bash в Mac OS X подтверждает это. То есть каждая int возвращающая функция возвращает что-то обратно, то же самое должно быть верно для функций, которые также возвращают другие типы. Если вы не вернетесь явно, то будет возвращено то, чего вы не знаете. Если вы не можете вернуть что-либо в конце функции, попробуйте вернуть void, чтобы посмотреть, не нарушит ли он код. Если он выходит из строя, функции требуют больше работы, в противном случае продолжайте использовать тип возврата void.

0 голосов
/ 12 июля 2010

Если вы не можете ничего вернуть, вы можете подумать о том, чтобы вызвать исключение или, как уже было сказано, изменить код.

0 голосов
/ 12 июля 2010

Введите return 0; или return -1;, если это ошибка и ваши целые числа без ошибок имеют положительную подпись.

...