#c #macros #c-preprocessor
#c #макросы #c-препроцессор
Вопрос:
В следующем фрагменте у меня есть struct IndexError
, который я возвращаю, когда пользователь допустил ошибку, используя мою библиотеку. У меня есть функциональный макрос, который приводит указатель на IndexError*
и перечисление, оба вызываются INDEX_ERROR
.
enum errors {
SUCCESS,
INVALID_ARGUMENT,
INDEX_ERROR
};
struct Error {
char error_buff[BUFSIZ];
};
typedef struct Error Error;
struct IndexError {
Error parent;
size_t invalid_index;
// etc.
};
typedef struct IndexError IndexError;
#define INDEX_ERROR(obj) ((IndexError*) obj)
Примером того, как я бы использовал это, является:
size_t pos = 4;
int IndexPointer* error = NULL;
int status = array_remove_item(my_array, pos, amp;error);
Затем я проверяю статус. Если он не возвращает SUCCESS
, я бы проверил ошибку, потому что это должно указывать на вновь созданную ошибку.
Реализация одной из функций массива может выглядеть следующим образом:
int array_remove_item(Array* array, size_t pos, Error** error_out)
{
Error* error = NULL;
if(pos >= array->size) {
index_error_create(INDEX_ERROR(amp;error), pos); // use casting macro.
*error_out = error;
return INDEX_ERROR; // is this the macro or the value from the errors enum?
}
priv_array_remove_item(array, pos);
return SUCCESS;
}
Итак, мой вопрос в том, return INDEX_ERROR;
вернет ли INDEX_ERROR
значение из перечисления, или препроцессор укусит меня, потому что мое именование неудобно?
Комментарии:
1. Замена макроса происходит на отдельном этапе, прежде чем другие идентификаторы будут переданы через компилятор. Эта ссылка на этап перевода могла бы быть полезной.
2. Макросы расширяются перед компиляцией. В результате ваше значение enum
INDEX_ERROR
будет заменено текстом макроса. Однако я ожидал бы, что препроцессор пожалуется, что вы ссылаетесь на макрос без параметра.3. Напрямую не связаны, но идентификаторы
_This _Sort
зарезервированы для реализации для любого использования. Вы можете объявитьtypedef struct Error Error;
просто отлично.4. Также обратите внимание, что в C (а также C , но в будущем помечайте только язык, на котором вы на самом деле программируете, поскольку C и C в остальном являются двумя очень разными языками) символы, начинающиеся с подчеркивания и сопровождаемые заглавной буквой (например,
_Error
), зарезервированы во всех областях для компилятора и стандартной библиотеки. Как правило, вам не следует определять такие символы самостоятельно.5. @StoryTeller отредактировал и удалил подчеркивания
Ответ №1:
return INDEX_ERROR; // is this the macro or the value from the errors enum?
Это перечислитель. Это не может быть результатом расширения функционального макроса, потому что за ним не следует сразу левый парный (
маркер, поскольку для препроцессора требуется1.
Правда, он немного вонючий. Разные имена для макроса и перечислителя сделают код более понятным и самоочевидным без необходимости читать спецификацию языка, напечатанную мелким шрифтом.
Комментарии:
1. Эта ссылка не радует мой браузер, потому что соединение небезопасно.
2. @hetepeperfan — Серьезно? Я использую последнюю версию Chrome, и она отлично открывает ссылку (а chrome известен своей строгостью в отношении ссылок https).
3. Я использую Firefox, который поставляется с Ubuntu16.04, возможно, он немного устарел.
4. В любом случае, это идентификатор стандартного проекта, который я использовал (отредактированный в вопросе), и номер раздела. Вы можете проверить это из другого источника.