#c
#c
Вопрос:
Рассмотрим следующий код:
static inline StatusCode SomeHelperFunction(SomeType* arg)
{
return OtherFunction(amp;arg->member, "foo", "bar");
}
static StatusCode OtherFunction(SomeType2* param, const char* param2, const char* param3)
{
if (param == NULL) /* return error status code */
/* do some stuff and return OK status code */
}
Проблема в том, что OtherFunction
невозможно принять NULL (и он проверяет его и возвращает правильный экземпляр StatusCode
. С помощью данной вспомогательной функции я не могу гарантировать, что arg
это не null и разыменование не приведет к сбою приложения. Таким образом, защита null внутри SomeHelperFunction
кажется разумной. Но это встроенная функция, и оператор if может ее нарушить. Я думаю, есть два варианта.
- Не проверяйте null и просто дайте миру сгореть
- Проверьте и, возможно, нарушите встроенные преимущества (что, если у меня есть 100 таких функций)
Что вы делаете в этом случае?
Комментарии:
1. Я не понимаю: какое отношение inline имеет к проверке null?
2. И что заставляет вас думать, что
if
оператор в вспомогательной функции может нарушить егоinline
или нет?3. Я думаю, что в определенных случаях строгий компилятор не разрешил бы иметь оператор if внутри встроенной функции, тем самым удаляя из него inline (я ошибаюсь)?
4. Компилятору не требуется выполнять встроенную оптимизацию вспомогательной функции независимо от того, но я не вижу особых причин ожидать, что использование
if
оператора будет существенным фактором в решении компилятора.5. Вы также можете использовать макрос вместо встроенной функции, чтобы принудительно «встраивать» везде : #define SomeHelperFunction(arg) ((arg) ? OtherFunction(amp;(arg)-> member, «foo», «bar»): возвращает ОШИБКУ)
Ответ №1:
TL; DR:
Поместите условие в код и не беспокойтесь об этом.
Компиляторы являются мощными:
Рассмотрим код:
static int SomeHelperFunction(int* arg) {
return Foo(amp;arg, "foo", "bar");
}
static inline int SomeInlineHelperFunction(int* param) {
if (param == NULL)
return 3;
return Foo(amp;param, "foo", "bar");
}
void entrypoint() {
int x;
SomeHelperFunction(amp;x);
SomeInlineHelperFunction(amp;x);
}
clang будет встроен SomeInlineHelperFunction
и SomeHelperFunction
, и он даже оптимизирует проверку null, поскольку он может определить, что невозможно быть ложным.
entrypoint():
push rbx
sub rsp, 16
lea rbx, [rsp 12]
mov qword ptr [rsp], rbx
mov rdi, rsp
mov esi, offset .L.str
mov edx, offset .L.str.1
call Foo(int**, char const*, char const*)
mov qword ptr [rsp], rbx
mov rdi, rsp
mov esi, offset .L.str
mov edx, offset .L.str.1
call Foo(int**, char const*, char const*)
add rsp, 16
pop rbx
ret
.L.str:
.asciz "foo"
.L.str.1:
.asciz "bar"