Что происходит, когда встроенная функция передается как параметр в C?

StackOverflow https://stackoverflow.com/questions/1029959

  •  06-07-2019
  •  | 
  •  

Вопрос

Сегодня я писал код на C для сортировки массива структур, используя быструю сортировку с пользовательской функцией сравнения для определения их порядка.

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

В моем исходном коде я объявил функцию сравнения inline . В моем новом коде я сохранил объявление inline , хотя для меня это не имело особого смысла, учитывая, что функция передавалась как параметр. Однако компилятор не жаловался!

Мой вопрос: имеет ли здесь какое-либо влияние объявление inline , или это просто рекомендация для компилятора, которая игнорируется?

Оригинальный код:

typedef struct _CGRect {
    CGPoint origin;
    CGSize size;
} CGRect;

typedef enum _NSComparisonResult {
     NSOrderedAscending = -1,
     NSOrderedSame,
     NSOrderedDescending
} NSComparisonResult;

static inline NSComparisonResult CGRectCompareRowsFirst(CGRect r1, CGRect r2)
{
    if (r1.origin.y < r2.origin.y)
        return NSOrderedAscending;
    else if (r1.origin.y > r2.origin.y)
        return NSOrderedDescending;
    else
    {
        if (r1.origin.x < r2.origin.x)
            return NSOrderedAscending;
        else if (r1.origin.x > r2.origin.x)
            return NSOrderedDescending;
        else
            return NSOrderedSame;
    }
}

static void CGRectQuicksortRowsFirst(CGRect *left, CGRect *right)
{
    if (right > left) {
        CGRect pivot = left[(right-left)/2];
        CGRect *r = right, *l = left;
        do {
            while (CGRectCompareRowsFirst(*l, pivot) == NSOrderedAscending) l++;
            while (CGRectCompareRowsFirst(*r, pivot) == NSOrderedDescending) r--;
            if (l <= r) {
                CGRect t = *l;
                *l++ = *r;
                *r-- = t;
            }
        } while (l <= r);
        CGRectQuicksortRowsFirst(left, r);
        CGRectQuicksortRowsFirst(l, right);
    }
}

static void CGRectSortRowsFirst(CGRect *array, int length)
{
    CGRectQuicksortRowsFirst(array, array+length-1);
}

Новый код:

static inline NSComparisonResult CGRectCompareRowsFirst(const void *s1, const void *s2)
{
    CGRect r1 = *(CGRect *)s1, r2 = *(CGRect *)s2;

    if (r1.origin.y < r2.origin.y)
        return NSOrderedAscending;
    else if (r1.origin.y > r2.origin.y)
        return NSOrderedDescending;
    else
    {
        if (r1.origin.x < r2.origin.x)
            return NSOrderedAscending;
        else if (r1.origin.x > r2.origin.x)
            return NSOrderedDescending;
        else
            return NSOrderedSame;
    }
}

static void quick(CGRect *left, CGRect *right, NSComparisonResult(*f)(const void *, const void *))
{
    if (right > left) {
        CGRect pivot = left[(right-left)/2];
        CGRect *r = right, *l = left;
        do {
            while (f(&*l, &pivot) == NSOrderedAscending) l++;
            while (f(&*r, &pivot) == NSOrderedDescending) r--;
            if (l <= r) {
                CGRect t = *l;
                *l++ = *r;
                *r-- = t;
            }
        } while (l <= r);
        quick(left, r, f);
        quick(l, right, f);
    }
}

static void CGRectSortRowsFirst(CGRect *array, int length)
{
    quick(array, array+length-1, CGRectCompareRowsFirst);
}
Это было полезно?

Решение

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

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

Встроенные и не встроенные версии могут и часто сосуществуют в одной скомпилированной программе.

Другие советы

Ключевое слово «inline» - это просто флаг компилятора, который указывает ему обрабатывать его по-другому, поскольку он будет копировать тело функции и заменять ее фактическим вызовом функции. Это повышение производительности, если у вас есть небольшая функция, которая повторно используется во многих местах вашего кода. Это изящная вещь для использования с аксессорами и модификаторами. В вашем случае, я думаю, вы могли бы оставить все как есть. Ты не делаешь ничего тяжелого. Разница скорее всего не будет заметна.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top