Проверка на НУЛЬ внутри встроенной функции

#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 может ее нарушить. Я думаю, есть два варианта.

  1. Не проверяйте null и просто дайте миру сгореть
  2. Проверьте и, возможно, нарушите встроенные преимущества (что, если у меня есть 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"
  

https://godbolt.org/z/zYfds8