简体   繁体   English

内联函数作为C中的参数传递时会发生什么?

[英]What happens when an inline function is passed as a parameter in C?

Today I was writing some C code to sort an array of structs using quicksort with a custom comparator function to determine their ordering. 今天我编写了一些C代码来使用带有自定义比较器功能的快速排序对结构数组进行排序,以确定它们的排序。

At first I wrote it with the call to the comparator function hard-coded into the quicksort function. 起初我用调用比特函数编写它,硬编码到quicksort函数中。 Then I thought perhaps it would be nicer to pass that function as an argument to a generic quicksort function. 然后我想也许将该函数作为参数传递给通用的快速排序函数会更好。

In my original code, I had declared the comparator function inline . 在我原来的代码中,我已经将比较器函数声明为inline In my new code, I kept the inline declaration, even though that didn't really make much sense to me, given that the function was being passed as a parameter. 在我的新代码中,我保留了inline声明,即使这对我来说没有多大意义,因为函数是作为参数传递的。 However, the compiler didn't complain! 但是,编译器没有抱怨!

My question is: is the inline declaration having any effect here, or is it merely a recommendation to the compiler which is being ignored? 我的问题是: inline声明在这里有任何影响,还是仅仅是对编译器的建议被忽略了?

Original code: 原始代码:

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

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

Inline is just a recommendation to the compiler, and can be ignored. 内联只是对编译器的推荐,可以忽略。 This can happen for several reasons, such as if the function is too complex to be safely inlined. 这可能由于多种原因而发生,例如,如果函数太复杂而无法安全地内联。 If you pass it as a parameter to a function like above, the compiler will create the non-inlined version whose address will be passed to the function. 如果将它作为参数传递给上面的函数,编译器将创建非内联版本,其地址将传递给函数。

It may be possible that the compiler could still inline the function - for instance, during code generation the compiler could utilize the inline function hint replacing the call via a function pointer to just the expanded function; 编译器可能仍然可以内联函数 - 例如,在代码生成期间,编译器可以利用内联函数提示通过函数指针替换调用仅扩展函数; I am not sure if any current compiler would do that. 我不确定当前的编译器是否会这样做。

Inlined and non-inlined versions can and often do co-exist within one compiled program. 内联和非内联版本可以并且经常在一个编译的程序中共存。

The 'inline' keyword is simply a compiler flag that tells it to handle it differently in that it will copy the body of the function and replace it with the actual function call. 'inline'关键字只是一个编译器标志,告诉它以不同的方式处理它,因为它将复制函数体并将其替换为实际的函数调用。 This is a performance boost if you have a small function that gets reused in many locations in your code. 如果您有一个小函数可以在代码中的许多位置重用,则可以提高性能。 It's a neat thing to use with accessors and modifiers. 使用存取器和修改器是一件很好的事情。 In your case, I think you could leave it as it is. 在你的情况下,我认为你可以保持原样。 You're not doing anything heavy. 你没有做任何沉重的事情。 The difference will most likely not be noticeable. 差异很可能不明显。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM