将结构体数组传递给函数?

时间:2022-10-18 00:57:36

I would like learn how to pass, by reference, an array of structs to the second function called/executed from within the first function. My goal is to modify/change the contents of arbitrary struct from the second function only. The code below works, but, unfortunately, does not do exactly what I want to achieve. I would to have access to arbitrary struct within second function. In other words, I would like to process all structs (using for loop) within second function by calling/executing first function in main only once and not using for loop.

我想学习如何通过引用将一个结构体数组传递到第一个函数中调用/执行的第二个函数。我的目标是从第二个函数修改/修改任意结构的内容。下面的代码是有效的,但不幸的是,它并没有实现我想要实现的目标。我需要在第二个函数中访问任意结构体。换句话说,我希望在第二个函数中处理所有的结构体(使用for循环),只在main中调用/执行第一个函数一次,不使用for循环。

The second function, in the code below, is named passByReference_inner.

下面代码中的第二个函数名为passByReference_inner。

array_of_struct.h :

array_of_struct。h:

struct card
{
    int face;
    int nose;
};

typedef struct card HEAD ;

/* prototype */
extern void passByReference(HEAD **c);      /* first function */
extern void passByReference_inner(HEAD *c); /* second function */

first function: (passByReference)

第一个函数(passByReference):

#include <stdio.h>
#include "array_of_struct.h"

void passByReference(HEAD **c)
{
    passByReference_inner (*c);   /* second function */
}

second function: (passByReference_inner)

第二功能:(passByReference_inner)

#include <stdio.h>
#include "array_of_struct.h"

void passByReference_inner(HEAD *c)
{
    c->face = (c->face) + 1000;
    c->nose = (c->nose) + 2000;
}

main:

主要:

#include <stdio.h>
#include "array_of_struct.h"

int main(void)
{
    int             i;
    static HEAD     c[12];
    static HEAD *cptr[12];

    for ( i = 0; i < 12; i++ )
    {
        c[i].face = i + 30;
        c[i].nose = i + 60; 
        cptr[i]   = &c[i];
    }

    for ( i = 0; i < 12; i++ )
    {
        passByReference(&cptr[i]);  /* first function */
    }
    return 0;
}

4 个解决方案

#1


1  

Your second function is correct.

第二个函数是正确的。

A pointer to the first element of an array is effectively the same thing as the pointer to an array itself.

指向数组第一个元素的指针与指向数组本身的指针实际上是一样的。

What you should do is

你应该做的是!

void passByReference_inner(HEAD *c, size_t n)
{
}

So, you'll pass the pointer to the first element of the array, and the number of elements in the array, something like this:

你会把指针传递给数组的第一个元素,以及数组中元素的数量,像这样:

passByReference(c, sizeof(c)/sizeof(c[0]));

This will pass the pointer to the first element of the c array, and the number of elements in the array, to passByReference_inner(). sizeof(c) is the size of the entire array in bytes. sizeof(c[0]) is the size of an element in the array. So, if, for example, each struct is 10 bytes long (just an example), and you have an array of 12 structs, the size of the entire array is 120 bytes, and this calculates the value 120/10=12, the number of elements in the array, automatically.

这将把指针传递给c数组的第一个元素,以及数组中的元素数量,传递给passByReference_inner()。sizeof(c)是整个数组的字节数。sizeof(c[0])是数组中元素的大小。例如,如果每个struct都是10字节长(只是一个例子),你有一个12个struct的数组,整个数组的大小是120字节,这自动计算120/10=12,数组中的元素个数。

When you use the name of an array object, in C/C++ that automatically becomes a pointer to the first element of the array.

当您使用数组对象的名称时,在C/ c++中,它将自动成为指向数组第一个元素的指针。

In your function, you can work with the array in the following manner:

在您的函数中,可以按照以下方式处理数组:

void passByReference_inner(HEAD *c, size_t n)
{
    for (size_t i=0; i<n; i++)
    {
        HEAD *p=c+i;

        // p is now a pointer to the ith element of the array
    }
}

Adding an integer n to a pointer advances the pointer to the next nth element of an array. Adding an integer value to a pointer doesn't advance the pointer by this number of bytes, but by the number of bytes in the object the pointer points to, multiplied by the number you're adding (or subtracting, same thing). That makes pointer arithmetic do the right thing.

向指针添加一个整数n将使指针指向数组的下一个第n个元素。向指针添加一个整数值并不会使指针向前移动这么多字节,而是通过指针指向的对象中的字节数,乘以要添加(或减去)的数字。这使得指针算法做对了。

#2


3  

I think what you are trying to do is this

我认为你要做的是

#include <stdio.h>

struct card
{
    int face;
    int nose;
};

typedef struct card HEAD ;

/* prototype */
void passByReference(HEAD *c, int count);      /* first function */
void passByReference_inner(HEAD *c); /* second function */

void passByReference(HEAD *c, int count)
{
    int i;
    for (i = 0 ; i < count ; i++)
        passByReference_inner (&(c[i]));   /* second function */
}

void passByReference_inner(HEAD *c)
{
    c->face = (c->face) + 1000;
    c->nose = (c->nose) + 2000;
}

int main(void)
{
    int  i;
    HEAD c[12]; /* you don't need static here (do you know what static is for?) */

    for ( i = 0; i < 12; i++ )
    {
        c[i].face = i + 30;
        c[i].nose = i + 60;
    }
    /* 
     * the element count of the array is sizeof(c) / sizeof(c[0]) 
     *    (totalSizeOfArray) / (indivudualElementSizeOfArray).
     */
    passByReference(c, sizeof(c) / sizeof(c[0]));  /* first function */

    return 0;
}

what you should know is that arrays in c decay to a pointer that points to their first element when passed as parameters to functions.

您应该知道的是,当数组作为参数传递给函数时,数组会衰减到指向第一个元素的指针。

Since you want to process all the structs in the second function, I don't see the need for the first function, anyway this is how you would do it then

既然你想要处理第二个函数的所有结构,我不认为第一个函数有必要,不管怎样,这就是你要做的。

#include <stdio.h>

struct card
{
    int face;
    int nose;
};

typedef struct card HEAD ;

/* prototype */
void passByReference(HEAD *const c, int count);      /* first function */
void passByReference_inner(HEAD *const c, int count); /* second function */

void passByReference(HEAD *const c, int count)
{
    passByReference_inner(c, count);   /* second function */
}

/* HEAD *const c prevents the pointer c to be changed
 * this way it will never point anywhere else.
 *
 * And you can be sure to alter the original data.
 */
void passByReference_inner(HEAD *const c, int count)
{
    for (int i = 0 ; i < count ; ++i)
    {
        c[i].face = (c[i].face) + 1000;
        c[i].nose = (c[i].nose) + 2000;
    }
}

int main(void)
{
    int  i;
    HEAD c[12]; /* you don't need static here (do you know what static is for?) */

    for ( i = 0; i < 12; i++ )
    {
        c[i].face = i + 30;
        c[i].nose = i + 60;
    }
    /* 
     * the element count of the array is sizeof(c) / sizeof(c[0]) 
     *    (totalSizeOfArray) / (indivudualElementSizeOfArray).
     */
    passByReference(c, sizeof(c) / sizeof(c[0]));  /* first function */

    return 0;
}

since you are effectively passing a pointer, you alter it's contents directly in both functions the first and the second.

因为您正在有效地传递一个指针,所以您直接在第一个和第二个函数中修改它的内容。

One more thing, you don't really need the static keyword, specially in main(), static keeps the value of the variable between function calls, and since main() will normally be called only once in the lifetime of the program... it doesn't make much sense to use static there.

还有一点,您并不需要静态关键字,特别是在main()中,静态保持函数调用之间的变量值,并且由于main()通常在程序的生命周期中只调用一次……在那里使用静态是没有多大意义的。

#3


0  

  • The following code compiles cleanly.
  • 下面的代码编译得很干净。
  • The following code moves the increment values loop
    to inside the passByReference() function.
  • 下面的代码将递增值循环移动到passByReference()函数中。

/* 
 * Note: guard code is used in a header file
 *       so the header file can only be included once
 *       in each compilation unit 
 */

// note the inclusion of a 'guard' wrapper
// begin: array_of_struct.h file
#ifndef ARRAY_OF_STRUCT_H
#define ARRAY_OF_STRUCT_H

struct card
{
    int face;
    int nose;
};

// dont obsecure the code with useless typedef statements
//typedef struct card HEAD ;

#define MAX_CARDS (12)

/* prototype */
extern void passByReference(struct card *pCards);      /* first function */
extern void passByReference_inner(struct card *pCard); /* second function */
#endif
// end: array_of_struct.h


//first function: (passByReference), in different file

#include <stdio.h>
#include "array_of_struct.h" 

void passByReference(struct card *pCards)
{
    int i=0; // loop index

    for(i=0;i<MAX_CARDS;i++)
    {
        passByReference_inner (&pCards[i]);   /* second function */
    } // end for
} // end function: passByReference

// second function: (passByReference_inner), in different file

#include <stdio.h>
#include "array_of_struct.h"

void passByReference_inner(struct card *pCard)
{
    pCard->face = (pCard->face) + 1000;
    pCard->nose = (pCard->nose) + 2000;
} // end function: passByReference_inner

//main, in a different file

#include <stdio.h>
#include "array_of_struct.h"

int main()
{
    int i = 0; // loop index
    static struct card     cards[MAX_CARDS];

    for ( i = 0; i < MAX_CARDS; i++ )
    {
        cards[i].face = i + 30;
        cards[i].nose = i + 60;
    } // end for

    passByReference(&cards[0]);  /* first function gets ptr to whole array*/
    // could also be written as:
    // passByReference(cards);

    return 0;
} // end function: main

#4


0  

I've analyzed all three solutions (iharob, user3629249, Sam Varshavchik) and came to the conclusion that Sam Varshavchik and the second solution from iharob were right on the money. The first iharob's solution and user3629249 solution are, in essence, equal. They moved for loop from main to the first function. The second solution of the iharob's post matches the requirements from the initial post. Sam's solution gave me enough hints/instructions for 'how to move for loop from the main to the second function (which was, basically, what I did not know how to do it and therefore asked for help).

我分析了所有三种解决方案(iharob, user3629249, Sam Varshavchik),得出的结论是,Sam Varshavchik和iharob的第二个解决方案是正确的。第一个iharob解决方案和user3629249解决方案在本质上是相等的。他们将for循环从主函数移动到第一个函数。iharob职位的第二个解决方案与最初职位的要求相匹配。Sam的解决方案给了我足够的提示/说明,告诉我如何将循环从主函数移动到第二个函数(基本上,这是我不知道怎么做的,因此请求帮助)。

So, to make long story short, here is the source code which implements almost all suggestions from all contributors. The code compiles cleanly, so, beginners like me, can take it as-is and learn few details about pointer to pointer, pointer arithmetic and about array of structs.

因此,长话短说,下面是实现所有贡献者几乎所有建议的源代码。代码编译得很干净,因此,像我这样的初学者可以按原样进行,并学习关于指针、指针算法和结构数组的一些细节。

array_of_struct.h (header file)

array_of_struct。h(头文件)

#ifndef ARRAY_OF_STRUCT_H
#define ARRAY_OF_STRUCT_H

/* HEAD structure definition */
typedef struct
{
    int face;
    int nose;
} HEAD;       // end structure HEAD

#define MAX_HEADS (12)

/* prototype */
extern void passByReference(HEAD **c, size_t n);
extern void passByReference_inner(HEAD *c, size_t n);

#endif

passByReference.c (first function)

passByReference。c(第一个函数)

#include <stdio.h>
#include "array_of_struct.h"

void passByReference(HEAD **c, size_t n)
{
    passByReference_inner (*c, n);
}

passByReference_inner.c (second function)

passByReference_inner。c(第二个函数)

#include <stdio.h>
#include "array_of_struct.h"

void passByReference_inner(HEAD *c, size_t n)
{
    int   i;
    HEAD *p;

    printf("\nPOINTER ARITHMETIC: The value of struct's  members after PASS BY REFERENCE \n");
    for ( i = 0; i < n; i++ )
    {
        p = c + i;

        p->face = (p->face) + 1000;
        p->nose = (p->nose) + 2000;
        printf("struct[%i].face = %d  \n",i, p[0].face);
        printf("struct[%i].nose = %d  \n",i, p[0].nose);
    }

    printf("\nARRAY INDEX MATH: The value of struct's  members after PASS BY REFERENCE\n");
    printf("[NOTE: structs were updated in the for loop above]\n");
    for ( i = 0; i < n; i++ )
    {
        printf("struct[%i].face = %d  \n",i, c[i].face);
        printf("struct[%i].nose = %d  \n",i, c[i].nose);
    }
}

main.c

c

#include <stdio.h>
#include "array_of_struct.h"

int main(void)
{
    int     i;
    HEAD    c[MAX_HEADS];
    HEAD   *cptr;
    size_t  n;

    n = (sizeof(c) / sizeof(c[0]);

    printf("\nINITIALIZATION of all struct's  members\n");
    for ( i = 0; i < n; i++ )
    {
        c[i].face = i + 30;
        c[i].nose = i + 60; 
        printf("struct[%i].face = %d\n",i, c[i].face);
        printf("struct[%i].nose = %d\n",i, c[i].nose);
    }

    cptr = &c[0];
    passByReference(&cptr, n); 

    return 0;
}

#1


1  

Your second function is correct.

第二个函数是正确的。

A pointer to the first element of an array is effectively the same thing as the pointer to an array itself.

指向数组第一个元素的指针与指向数组本身的指针实际上是一样的。

What you should do is

你应该做的是!

void passByReference_inner(HEAD *c, size_t n)
{
}

So, you'll pass the pointer to the first element of the array, and the number of elements in the array, something like this:

你会把指针传递给数组的第一个元素,以及数组中元素的数量,像这样:

passByReference(c, sizeof(c)/sizeof(c[0]));

This will pass the pointer to the first element of the c array, and the number of elements in the array, to passByReference_inner(). sizeof(c) is the size of the entire array in bytes. sizeof(c[0]) is the size of an element in the array. So, if, for example, each struct is 10 bytes long (just an example), and you have an array of 12 structs, the size of the entire array is 120 bytes, and this calculates the value 120/10=12, the number of elements in the array, automatically.

这将把指针传递给c数组的第一个元素,以及数组中的元素数量,传递给passByReference_inner()。sizeof(c)是整个数组的字节数。sizeof(c[0])是数组中元素的大小。例如,如果每个struct都是10字节长(只是一个例子),你有一个12个struct的数组,整个数组的大小是120字节,这自动计算120/10=12,数组中的元素个数。

When you use the name of an array object, in C/C++ that automatically becomes a pointer to the first element of the array.

当您使用数组对象的名称时,在C/ c++中,它将自动成为指向数组第一个元素的指针。

In your function, you can work with the array in the following manner:

在您的函数中,可以按照以下方式处理数组:

void passByReference_inner(HEAD *c, size_t n)
{
    for (size_t i=0; i<n; i++)
    {
        HEAD *p=c+i;

        // p is now a pointer to the ith element of the array
    }
}

Adding an integer n to a pointer advances the pointer to the next nth element of an array. Adding an integer value to a pointer doesn't advance the pointer by this number of bytes, but by the number of bytes in the object the pointer points to, multiplied by the number you're adding (or subtracting, same thing). That makes pointer arithmetic do the right thing.

向指针添加一个整数n将使指针指向数组的下一个第n个元素。向指针添加一个整数值并不会使指针向前移动这么多字节,而是通过指针指向的对象中的字节数,乘以要添加(或减去)的数字。这使得指针算法做对了。

#2


3  

I think what you are trying to do is this

我认为你要做的是

#include <stdio.h>

struct card
{
    int face;
    int nose;
};

typedef struct card HEAD ;

/* prototype */
void passByReference(HEAD *c, int count);      /* first function */
void passByReference_inner(HEAD *c); /* second function */

void passByReference(HEAD *c, int count)
{
    int i;
    for (i = 0 ; i < count ; i++)
        passByReference_inner (&(c[i]));   /* second function */
}

void passByReference_inner(HEAD *c)
{
    c->face = (c->face) + 1000;
    c->nose = (c->nose) + 2000;
}

int main(void)
{
    int  i;
    HEAD c[12]; /* you don't need static here (do you know what static is for?) */

    for ( i = 0; i < 12; i++ )
    {
        c[i].face = i + 30;
        c[i].nose = i + 60;
    }
    /* 
     * the element count of the array is sizeof(c) / sizeof(c[0]) 
     *    (totalSizeOfArray) / (indivudualElementSizeOfArray).
     */
    passByReference(c, sizeof(c) / sizeof(c[0]));  /* first function */

    return 0;
}

what you should know is that arrays in c decay to a pointer that points to their first element when passed as parameters to functions.

您应该知道的是,当数组作为参数传递给函数时,数组会衰减到指向第一个元素的指针。

Since you want to process all the structs in the second function, I don't see the need for the first function, anyway this is how you would do it then

既然你想要处理第二个函数的所有结构,我不认为第一个函数有必要,不管怎样,这就是你要做的。

#include <stdio.h>

struct card
{
    int face;
    int nose;
};

typedef struct card HEAD ;

/* prototype */
void passByReference(HEAD *const c, int count);      /* first function */
void passByReference_inner(HEAD *const c, int count); /* second function */

void passByReference(HEAD *const c, int count)
{
    passByReference_inner(c, count);   /* second function */
}

/* HEAD *const c prevents the pointer c to be changed
 * this way it will never point anywhere else.
 *
 * And you can be sure to alter the original data.
 */
void passByReference_inner(HEAD *const c, int count)
{
    for (int i = 0 ; i < count ; ++i)
    {
        c[i].face = (c[i].face) + 1000;
        c[i].nose = (c[i].nose) + 2000;
    }
}

int main(void)
{
    int  i;
    HEAD c[12]; /* you don't need static here (do you know what static is for?) */

    for ( i = 0; i < 12; i++ )
    {
        c[i].face = i + 30;
        c[i].nose = i + 60;
    }
    /* 
     * the element count of the array is sizeof(c) / sizeof(c[0]) 
     *    (totalSizeOfArray) / (indivudualElementSizeOfArray).
     */
    passByReference(c, sizeof(c) / sizeof(c[0]));  /* first function */

    return 0;
}

since you are effectively passing a pointer, you alter it's contents directly in both functions the first and the second.

因为您正在有效地传递一个指针,所以您直接在第一个和第二个函数中修改它的内容。

One more thing, you don't really need the static keyword, specially in main(), static keeps the value of the variable between function calls, and since main() will normally be called only once in the lifetime of the program... it doesn't make much sense to use static there.

还有一点,您并不需要静态关键字,特别是在main()中,静态保持函数调用之间的变量值,并且由于main()通常在程序的生命周期中只调用一次……在那里使用静态是没有多大意义的。

#3


0  

  • The following code compiles cleanly.
  • 下面的代码编译得很干净。
  • The following code moves the increment values loop
    to inside the passByReference() function.
  • 下面的代码将递增值循环移动到passByReference()函数中。

/* 
 * Note: guard code is used in a header file
 *       so the header file can only be included once
 *       in each compilation unit 
 */

// note the inclusion of a 'guard' wrapper
// begin: array_of_struct.h file
#ifndef ARRAY_OF_STRUCT_H
#define ARRAY_OF_STRUCT_H

struct card
{
    int face;
    int nose;
};

// dont obsecure the code with useless typedef statements
//typedef struct card HEAD ;

#define MAX_CARDS (12)

/* prototype */
extern void passByReference(struct card *pCards);      /* first function */
extern void passByReference_inner(struct card *pCard); /* second function */
#endif
// end: array_of_struct.h


//first function: (passByReference), in different file

#include <stdio.h>
#include "array_of_struct.h" 

void passByReference(struct card *pCards)
{
    int i=0; // loop index

    for(i=0;i<MAX_CARDS;i++)
    {
        passByReference_inner (&pCards[i]);   /* second function */
    } // end for
} // end function: passByReference

// second function: (passByReference_inner), in different file

#include <stdio.h>
#include "array_of_struct.h"

void passByReference_inner(struct card *pCard)
{
    pCard->face = (pCard->face) + 1000;
    pCard->nose = (pCard->nose) + 2000;
} // end function: passByReference_inner

//main, in a different file

#include <stdio.h>
#include "array_of_struct.h"

int main()
{
    int i = 0; // loop index
    static struct card     cards[MAX_CARDS];

    for ( i = 0; i < MAX_CARDS; i++ )
    {
        cards[i].face = i + 30;
        cards[i].nose = i + 60;
    } // end for

    passByReference(&cards[0]);  /* first function gets ptr to whole array*/
    // could also be written as:
    // passByReference(cards);

    return 0;
} // end function: main

#4


0  

I've analyzed all three solutions (iharob, user3629249, Sam Varshavchik) and came to the conclusion that Sam Varshavchik and the second solution from iharob were right on the money. The first iharob's solution and user3629249 solution are, in essence, equal. They moved for loop from main to the first function. The second solution of the iharob's post matches the requirements from the initial post. Sam's solution gave me enough hints/instructions for 'how to move for loop from the main to the second function (which was, basically, what I did not know how to do it and therefore asked for help).

我分析了所有三种解决方案(iharob, user3629249, Sam Varshavchik),得出的结论是,Sam Varshavchik和iharob的第二个解决方案是正确的。第一个iharob解决方案和user3629249解决方案在本质上是相等的。他们将for循环从主函数移动到第一个函数。iharob职位的第二个解决方案与最初职位的要求相匹配。Sam的解决方案给了我足够的提示/说明,告诉我如何将循环从主函数移动到第二个函数(基本上,这是我不知道怎么做的,因此请求帮助)。

So, to make long story short, here is the source code which implements almost all suggestions from all contributors. The code compiles cleanly, so, beginners like me, can take it as-is and learn few details about pointer to pointer, pointer arithmetic and about array of structs.

因此,长话短说,下面是实现所有贡献者几乎所有建议的源代码。代码编译得很干净,因此,像我这样的初学者可以按原样进行,并学习关于指针、指针算法和结构数组的一些细节。

array_of_struct.h (header file)

array_of_struct。h(头文件)

#ifndef ARRAY_OF_STRUCT_H
#define ARRAY_OF_STRUCT_H

/* HEAD structure definition */
typedef struct
{
    int face;
    int nose;
} HEAD;       // end structure HEAD

#define MAX_HEADS (12)

/* prototype */
extern void passByReference(HEAD **c, size_t n);
extern void passByReference_inner(HEAD *c, size_t n);

#endif

passByReference.c (first function)

passByReference。c(第一个函数)

#include <stdio.h>
#include "array_of_struct.h"

void passByReference(HEAD **c, size_t n)
{
    passByReference_inner (*c, n);
}

passByReference_inner.c (second function)

passByReference_inner。c(第二个函数)

#include <stdio.h>
#include "array_of_struct.h"

void passByReference_inner(HEAD *c, size_t n)
{
    int   i;
    HEAD *p;

    printf("\nPOINTER ARITHMETIC: The value of struct's  members after PASS BY REFERENCE \n");
    for ( i = 0; i < n; i++ )
    {
        p = c + i;

        p->face = (p->face) + 1000;
        p->nose = (p->nose) + 2000;
        printf("struct[%i].face = %d  \n",i, p[0].face);
        printf("struct[%i].nose = %d  \n",i, p[0].nose);
    }

    printf("\nARRAY INDEX MATH: The value of struct's  members after PASS BY REFERENCE\n");
    printf("[NOTE: structs were updated in the for loop above]\n");
    for ( i = 0; i < n; i++ )
    {
        printf("struct[%i].face = %d  \n",i, c[i].face);
        printf("struct[%i].nose = %d  \n",i, c[i].nose);
    }
}

main.c

c

#include <stdio.h>
#include "array_of_struct.h"

int main(void)
{
    int     i;
    HEAD    c[MAX_HEADS];
    HEAD   *cptr;
    size_t  n;

    n = (sizeof(c) / sizeof(c[0]);

    printf("\nINITIALIZATION of all struct's  members\n");
    for ( i = 0; i < n; i++ )
    {
        c[i].face = i + 30;
        c[i].nose = i + 60; 
        printf("struct[%i].face = %d\n",i, c[i].face);
        printf("struct[%i].nose = %d\n",i, c[i].nose);
    }

    cptr = &c[0];
    passByReference(&cptr, n); 

    return 0;
}