Pergunta

Hoje eu estava escrevendo algum código C para classificar uma matriz de estruturas usando o QuickSort com uma função de comparador personalizada para determinar sua ordem.

No começo, escrevi com a chamada para a função comparadora codificada na função Quicksort. Então eu pensei que talvez fosse mais agradável passar essa função como um argumento para uma função genérica do QuickSort.

No meu código original, eu havia declarado a função do comparador inline. No meu novo código, eu mantive o inline Declaração, embora isso não tenha realmente feito muito sentido para mim, já que a função estava sendo passada como um parâmetro. No entanto, o compilador não reclamou!

Minha pergunta é: é o inline Declaração tendo algum efeito aqui, ou é apenas uma recomendação ao compilador que está sendo ignorado?

Código original:

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

Novo Código:

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);
}
Foi útil?

Solução

O Inline é apenas uma recomendação para o compilador e pode ser ignorado. Isso pode acontecer por vários motivos, como se a função for complexa demais para ser inlinada com segurança. Se você o passar como um parâmetro para uma função como acima, o compilador criará a versão não-linada cujo endereço será passado para a função.

Pode ser possível que o compilador ainda possa incluir a função - por exemplo, durante a geração de código, o compilador poderia utilizar o dica de função embutida substituindo a chamada por meio de um ponteiro de função para apenas a função expandida; Não tenho certeza se algum compilador atual faria isso.

As versões inlinadas e não enlutadas podem e geralmente coexistem em um programa compilado.

Outras dicas

A palavra -chave 'inline' é simplesmente um sinalizador do compilador que diz para lidar com ela de maneira diferente, pois copiará o corpo da função e a substituirá pela chamada de função real. Este é um aumento de desempenho se você tiver uma pequena função que é reutilizada em muitos locais em seu código. É uma coisa interessante de usar com acessadores e modificadores. No seu caso, acho que você poderia deixar o que está. Você não está fazendo nada pesado. A diferença provavelmente não será perceptível.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top