3

今天我正在编写一些 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);
}
4

2 回答 2

14

内联只是对编译器的建议,可以忽略。发生这种情况的原因有很多,例如函数太复杂而无法安全内联。如果将它作为参数传递给上述函数,编译器将创建非内联版本,其地址将传递给函数。

编译器可能仍然可以内联函数 - 例如,在代码生成期间,编译器可以利用内联函数提示通过函数指针替换调用,仅指向扩展函数;我不确定当前的编译器是否会这样做。

内联和非内联版本可以并且经常在一个编译程序中共存。

于 2009-06-22T23:53:00.620 回答
0

'inline' 关键字只是一个编译器标志,告诉它以不同的方式处理它,因为它将复制函数的主体并将其替换为实际的函数调用。如果您有一个可以在代码中的许多位置重用的小函数,这将提高性能。与访问器和修饰符一起使用是一件很好的事情。在你的情况下,我认为你可以保持原样。你没有做任何沉重的事情。差异很可能不明显。

于 2009-06-23T00:00:13.273 回答