2009-06-22 2 views
2

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

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

В моем первоначальном коде я объявил функцию компаратора 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); 
} 
+0

Почему бы не использовать стандартную библиотеку 'qsort()' function? Скорее всего, это будет быстро, если не быстрее, чем у вашей ручной работы, особенно если вы передадите функцию компаратора в вашу функцию. Это также скорее всего будет ошибкой. –

+0

Вы правы, это, вероятно, быстрее, чем мой новый код. Думаю, мой вопрос, вероятно, был бы «что произойдет, если я передам встроенную функцию qsort()?» – hatfinch

ответ

13

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

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

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

0

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

+0

Еще раз посмотрим на мой вопрос. Я знаю, что делает 'inline' - мне просто интересно, насколько важно передавать встроенную функцию в качестве аргумента другой функции. – hatfinch

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