2010-11-21 4 views
0
gcc 4.5.1 c89 

У меня есть функция, которая присваивает элементы следующей структуры:Что вернуть, если функция имеет ошибку?

static struct Config_t { 
    char protocol[LINE_SIZE]; 
    char mode[LINE_SIZE]; 
} *app_config = NULL; 

Функция с помощью таНос и MemSet для назначения и очистить память.

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

char* get_mode() 
{ 
    if(app_config->mode != NULL) { 
     return app_config->mode; 
    } 
    return NULL; 
} 

Здесь я проверяю, что значение было назначено. И возвращать NULL, если это не так. Поэтому в вызывающей функции я могу проверить, возвращается ли NULL. Однако, если есть лучший способ сделать это?

Большое спасибо за любые предложения,

+3

Я из практики с C, но 'mode' не может быть' NULL', не так ли? 'app_config', безусловно, может быть' NULL', но ваш 'mode' определяется как массив, неотъемлемая часть структуры, а не как указатель. У вас будет либо структура, либо нет, но у вас не будет * part * структуры. Если 'mode' были определены как' char * mode', это было бы иначе. –

+2

просто верните режим: 'return app_config-> mode;' без проверки. – khachik

+0

@ T.J Режим - это массив. Однако это будет затухать в указатель. Мне просто интересно, что вернуть, если элемент режима, например, не получил никакого значения. Благодарю. – ant2009

ответ

3

В C, возвращаясь NULL для состояния ошибки является стандартной практикой для функций, возвращающих указатели, так что вы в хорошей форме там. (Для функций, которые не возвращают указатели, обычная условность является возвращение 0 на успех и ненулевым кодом ошибки на ошибки.)


Отдельно, и, возможно, немного не по теме: mode может» t be NULL, правда, не правда ли? app_config, безусловно, может быть NULL, это указатель на структуру, но ваш mode определяется как массив, неотъемлемая часть структуры, а не как указатель. У вас будет либо структура, либо нет, но у вас не будет только часть структуры. Простое распределение памяти для структуры будет выделять символы LINE_SIZE для mode; фактически, sizeof(struct Config_t) == LINE_SIZE + LINE_SIZE, структура - это массив символов, за которым следует другой массив символов. Нет указателей (кроме app_config, потому что вы определили его как указатель на структуру).

Следовательно, чтобы полностью выделить ваш struct Config_t, просто сделать это:

app_config = malloc(sizeof(*app_config)); 

(. Или app_config = malloc(sizeof(struct Config_t)); если ваша платформа не позволит выше), что выделяет mode, больше ничего не требуется.

Если mode были определены как char *, что будет по-другому:

static struct Config_t { 
    char *protocol; 
    char *mode; 
} *app_config = NULL; 

Теперь sizeof(struct Config_t) == 2 * sizeof(void*) (смотри ниже), сама структура состоит только из двух указателей, а не какие-либо данные, которые они могут указывать. Выделение структуры не выделяет для них любое хранилище.

#include <stdio.h> 

#define LINE_SIZE (200) 

struct Config_t { 
    char protocol[LINE_SIZE]; 
    char mode[LINE_SIZE]; 
}; 
struct Config_t_with_pointers { 
    char *protocol; 
    char *mode; 
}; 

int main(int argc, char* argv[]) 
{ 
    printf("sizeof(struct Config_t) = %zu\n", sizeof(struct Config_t)); 
    printf("sizeof(struct Config_t_with_pointers) = %zu\n", sizeof(struct Config_t_with_pointers)); 
    return 0; 
} 

(Учитывая ваш компилятор, я чувствовал себя свободно использовать формат z спецификатор для size_t аргументов, как и любой недавний НКУ имеет его [и это в стандарте C99, Мэтью говорит нам].)

выход (на моем 64-битной системе Linux):

sizeof(struct Config_t) = 400 
sizeof(struct Config_t_with_pointers) = 16
+0

Т. Дж., Ваше замечание выше верно, поэтому я бы упомянул его здесь. Каждый раз, когда у вас есть действительный 'Config_t', в нем есть массив режимов. –

+0

@Matthew: Спасибо; сделанный. –

+0

J., 'size_t' является стандартным C (C99). –

1

Исходя из определения встроенных функций C, например, получает(), возвращая NULL является идеальным способом, чтобы показать, что было невозможно выполнить задание или распределение.

+4

'get' на самом деле не является хорошей образцовой моделью для дизайна API ... –

+0

@Matthew: LOL !! –

+0

Теперь я понимаю, что вы упомянули об этом. Наверное, у него есть много недостатков, верно? Я имею в виду, что на некоторых компиляторах C мы получаем предупреждение, gets() - опасная функция :) –

1

Ну, поскольку единственная причина, по которой это происходит, - одно (если значение не было назначено), вам не нужно больше одного значения, чтобы различать их. Кроме того, NULL не является допустимым указателем, поэтому я не вижу в этом ничего плохого.

Если у вас было больше возможных ошибок, вы можете использовать errno.h для этой цели.

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