1

大家早上好,

我试图减少一个非常重复的函数,但是每个“重复”都有两个结构,结构 A.element1 设置结构 B.element1。目前我有 myFunction() 和大约十二个不同的 reqFunction() 调用来将 B 设置为 A。基本上我现在拥有的是:

void myFunction( structB *B )
{
    structA  A;

    if( reqGetFunction( GLOBAL_IN_1, ( void *)&A, SIZE ) != 0 )
    {
        A.element3 = -1;
        printf( "element3 failed\n" );
    }
    B->element7 = A.element3;   // A is gotten when regGetFunction() is called
    .
    .
    .
    if( reqGetFunction( GLOBAL_IN_12, ( void *)&A, SIZE ) != 0 )
    {
        A.element14 = -1;
        printf( "element14 failed\n" );
    }
    B->element18 = A.element14;
}

reqGetFunction() 无法更改。我有一个用于循环 GLOBAL_IN 的其他函数的静态全局数组,我可以将 structA A 设为静态全局。

我想要像 myFunctionSingle() 这样的东西来做一个块,而 myFunctionAll() 将有一个 for 循环来循环遍历 GLOBAL_IN 数组以及结构的 A 和 B 的元素并将它们输入到 myFunctionSingle()。

所以我想我真正的问题是如何像使用数组一样循环遍历结构的元素,因为那里的所有内容(如结构的设置和 reqGetFunction)都是一成不变的。我已经尝试了一些东西并四处搜索,但目前被难住了。老实说,我不确定这是否可能,甚至是否值得。预先感谢您的意见!

4

3 回答 3

2

您的函数调用因 1)GLOBAL_IN_XX 值 2)您修改的 A.elementxx 而不同。3)您修改的B.elementxx 您需要做的是创建一个包含GLOBAL_IN_XX 值的结构,一个指向A.element 和B.element 的指针,无论它们是什么类型,例如:

struct call_parms
{
int global_parm;
int* a_ptr;
int* b_ptr;
};

然后,您需要创建一个数组并相应地对其进行初始化,例如:

结构 call_parms callParmsArray[MAX_CALLS]= {{GLOBAL_IN_1,&A.element3,&(B->element5)}, ... };

然后,只需遍历数组并使用每个数组元素中指定的参数调用您的 reqGetFunction,类似于:

for(int i = 0; i<MAX_CALLS;i++)
{
reqGetFunction( callParmsArray[i].global_parm, callParmsArray[i].element_ptr, SIZE );
}

您可能还需要在结构中考虑指向 B->element 的指针并相应地处理它,因为它也是重复的。这可能涉及围绕 reqGetFunction() 创建一个包装器,该包装器也将处理 B 等:

struct call_parms
    {
    int global_parm;
    int* a_ptr;
    int* b_ptr;
    };

bool myReqFn(struct call_parms* parm)
{
bool res;
if( res = reqGetFunction( parm->global_parm, ( void *)&A, SIZE ) != 0 )
    {
        *(parm->a_ptr) = -1;
        printf( "element %d failed\n",parm->global_parm );
    }

*(parm->b_ptr) = *(parm->a_ptr);
return res;
}

for(int i = 0; i<MAX_CALLS;i++)
{
myReqFn( &callParmsArray[i]);
}

正如他们所说,其余的留给读者作为练习......

于 2013-05-23T15:41:46.150 回答
0

循环遍历我知道的结构的一种方法是使用指针数学。我不确定您的结构成员是哪种数据类型,但如果您有一组从 j 到 k 编号的相同数据类型,您的代码将如下所示:

(_datatype_)*a = &(A.elementj);
(_datatype_)*b = &(B.elementj);

int i;
for (i = j; i < k; i++)
{
    *(b + ((_sizeofdatatype) * (i - j)) = *(a + ((_sizeofdatatype) * (i - j));
}

编辑:当然,这也是假设您想按顺序复制每对相应的元素,但您可以调整它以获得所需的效果。

编辑:这也假设您同时分配整个结构(包括变量),所以要小心。

于 2013-05-23T15:39:17.417 回答
0

是什么GLOBAL_IN_XXX意思GLOBAL_IN[XXX]?并且GLOBAL_IN_XXX总是映射到A.element(XXX+2)? 它总是B.element(N+1) = A.elementN

我还将假设您不能更改A.element1, A.element2into A.element[],否则解决方案将相当简单,不是吗?

最便携的解决方案是知道 A 和 B 中每个元素的偏移量(如果结构中有数据对齐陷阱......如果你没有 N 个连续的 ELEMENT_TYPES 等可能会发生)

#include <stddef.h>


// NOTE: These arrays are clumbsy but avoid making assumptions about member alignment 
// in strucs. 
static size_t const A_Offsets[] = {
    offsetof(struct A, element1),
    offsetof(struct A, element2),
    offsetof(struct A, element3),
    ...
    ...
    offsetof(struct A, elementN) };


static size_t const B_Offsets[] = {
    offsetof(struct B, element1),
    offsetof(struct B, element2),
    offsetof(struct B, element3),
    ...
    ...
    offsetof(struct B, elementN) };


void myFunctionSingle( structB *B, unsigned int index )
{
    structA  A;
    ELEMENT_TYPE *elAPtr = (ELEMENT_TYPE *)((char *)A + A_Offsets[index + 2]);
    ELEMENT_TYPE *elBPtr = (ELEMENT_TYPE *)((char *)A + B_Offsets[index + 6]);


    if( reqGetFunction( GLOBAL_IN[index], ( void *)&A, SIZE ) != 0 )
    {            
        *elAPtr = -1;
        printf( "element%u failed\n", index);
    }
    *elBPtr = *elAPtr; // A is gotten when regGetFunction() is called      
}

void myFunction( structB *B )
{
    unsigned int i = 1;
    for(; i < MAX_INDEX; ++i)
        myFunctionSingle(B, i);
}

编辑:我不确定 offsetof() 的东西是否是必要的,因为如果你的结构中只有 ELEMENT_TYPE 数据,它们可能包装得很紧,但我不确定......如果它们包装得很紧,那么你不要'没有任何数据对齐问题,因此您可以使用波士顿沃克回答中提出的解决方案。

于 2013-05-23T15:51:08.000 回答