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

时间:2021-10-23 16:41:31

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. Then I thought perhaps it would be nicer to pass that function as an argument to a generic quicksort function.

起初我用调用比特函数编写它,硬编码到quicksort函数中。然后我想也许将该函数作为参数传递给通用的快速排序函数会更好。

In my original code, I had declared the comparator function 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. 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?

我的问题是:内联声明在这里有任何影响,还是仅仅是对编译器的建议被忽略了?

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

2 个解决方案

#1


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.

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

#2


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. 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.

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

#1


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.

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

#2


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. 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.

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