2009-06-22 3 views
2

Heute schrieb ich einen C-Code, um ein Array von Strukturen mithilfe von Quicksort mit einer benutzerdefinierten Vergleichsfunktion zu sortieren, um deren Reihenfolge zu bestimmen.Was passiert, wenn eine Inline-Funktion als Parameter in C übergeben wird?

Zuerst schrieb ich es mit dem Aufruf der Komparatorfunktion fest in die Quicksort-Funktion codiert. Dann dachte ich, es wäre vielleicht netter, diese Funktion als Argument für eine generische Quicksort-Funktion zu übergeben.

In meinem ursprünglichen Code hatte ich die Komparatorfunktion inline erklärt. In meinem neuen Code habe ich die inline Deklaration beibehalten, obwohl das für mich nicht viel Sinn ergeben hat, da die Funktion als Parameter übergeben wurde. Der Compiler hat sich jedoch nicht beschwert!

Meine Frage ist: hat die inline Deklaration hier irgendwelche Auswirkungen, oder ist es nur eine Empfehlung an den Compiler, die ignoriert wird?

Originalcode:

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); 
} 

Neuer Code:

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

Warum nicht die Standardbibliothek 'qsort()' Funktion verwenden? Es ist wahrscheinlich so schnell wie, wenn nicht schneller als Ihre handgefertigte, vor allem, wenn Sie die Komparatorfunktion an Ihre Funktion übergeben. Es ist auch eher fehlerfrei. –

+0

Du hast Recht, das ist wahrscheinlich schneller als mein neuer Code. Ich denke, meine Frage sollte wahrscheinlich lauten: "Was passiert, wenn ich eine Inline-Funktion an qsort() übergebe?" – hatfinch

Antwort

13

Inline ist nur eine Empfehlung an den Compiler, und kann ignoriert werden. Dies kann verschiedene Ursachen haben, z. B. wenn die Funktion zu komplex ist, um sicher inline zu sein. Wenn Sie es als Parameter an eine Funktion wie oben übergeben, erstellt der Compiler die nichtlineare Version, deren Adresse an die Funktion übergeben wird.

Es könnte sein, dass der Compiler die Funktion noch inline einbinden könnte - zum Beispiel könnte der Compiler während der Codegenerierung den Inline-Funktionshinweis verwenden, der den Aufruf über einen Funktionszeiger auf die erweiterte Funktion setzt; Ich bin mir nicht sicher, ob ein aktueller Compiler das tun würde.

Inlined- und nicht-inlined-Versionen können und koexistieren oft in einem kompilierten Programm.

0

Das Schlüsselwort 'inline' ist einfach ein Compiler-Flag, das besagt, dass es anders damit umgehen muss, dass es den Körper der Funktion kopiert und durch den tatsächlichen Funktionsaufruf ersetzt. Dies ist ein Leistungsschub, wenn Sie eine kleine Funktion haben, die an vielen Stellen in Ihrem Code wiederverwendet wird. Es ist eine nette Sache mit Accessoren und Modifikatoren zu verwenden. In deinem Fall glaube ich, du könntest es so lassen wie es ist. Du machst nichts Schweres. Der Unterschied wird höchstwahrscheinlich nicht auffallen.

+0

Sehen Sie sich meine Frage noch einmal an. Ich weiß, was 'inline' tut - ich habe mich nur gefragt, wie sinnvoll es ist, eine Inline-Funktion als Argument an eine andere Funktion zu übergeben. – hatfinch

Verwandte Themen