指针访问结构体成员

3

我有一个结构体,我将其作为常量指针传递给函数,我的问题是:以下两个updatedFields函数的实现有什么区别:

typedef struct
{
    int spec[100];
    int spec1[200];
    int spec2[200];
    int spec3[500];
    int spec4[100];
    int spec5[700];
    float value[100];
    char desc[1000]:
}t_product;



void updateFields_1(t_product const* context)
{

    int i,buffer[1500];
    int * pt_int;

    pt_int = (int*)context->spec1;      
    for(i = 0; i < 200; i++)
    {
        buffer[i] = pt_int[i];
    }

    pt_int = (int*)context->spec3;        
    for(i = 0; i < 500; i++)
    {
        buffer[i] = pt_int[i];
    }

    ...
}

void updateFields_2(t_product const* context)
{

    int i,buffer[1500];

    for(i = 0; i < 200; i++)
    {
        buffer[i] = context->spec1[i];
    }

    for(i = 0; i < 500; i++)
    {
        buffer[i] = context->spec3[i];
    }

    ...
}

int main(void)
{
    t_product prod;

    /* Initialisation of the structure */
    ...

    updateField(&prod);

}

我的意思是,使用指向结构体成员(指向数组的指针)的指针是否有任何优势,而不是直接访问结构体成员。

这可能是一个愚蠢的问题,但我不知道访问结构体成员是否会“消耗”更多操作。


1
请在 pt_int = (int*)context->spec3; 中去掉强制类型转换。这些类型已经兼容,不必要的强制类型转换可能会隐藏错误。 - M Oehm
你真的需要 for 循环吗?我认为,对于单个成员(数组类型),你可以直接使用 memcpy(),不是吗? - Sourav Ghosh
这是int main,而不是void main。我冒昧改正了它。 - Jens
2个回答

2
即使不进行优化,对您来说也不会更加昂贵。实际上,如果您不启用优化,您的pt_int示例可能会略微变差。这是因为context->spec3[i]没有比pt_int[i]解除更多的指针引用。 pt_int[i]只是一个指针加上一个偏移量,因此可以将访问写成@(ptr_int + 4 * i)。在context->spec3[i]中,它看起来像是解除了一个以上的指针引用,但事实并非如此。 spec3不是context中的值,而只是一个与context的偏移量。因此,您访问的地址将是@(context + 2000 + 4 * i)。只有一个指针访问。
现在您可以想知道@(context + 2000 + 4 * i)是否比@(ptr_int + 4 * i)更昂贵。这不是,因为大多数体系结构,包括x86,AMD64和ARM(即个人设备的100%),都具有使用常量偏移量进行访问的指令。此外,差异可能很快消失,一旦启用了微不足道的优化,因为context + 2000可以转换为单个context_2000(但编译器实际上不会这样做,因为它只会使性能变差)。

仅仅因为有一个使用常量偏移量进行访问的指令,就可以安全地说@(context + 2000 + 4*i)@(ptr_int + 4*i)的成本相同吗? - mastov
@ mastov 是的,因为这意味着对于两者来说是相同的指令,并且偏移量不会使这些指令更加昂贵(计算偏移量是微不足道的)。 - ElderBug

1

这样做确实会增加成本(每次迭代都需要解除原始指针的引用),但成本可能很小,一个相当不错的编译器将为您进行此优化。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接