【问题标题】:Passing an array of structs to a function?将结构数组传递给函数?
【发布时间】:2015-02-24 17:51:18
【问题描述】:

我想学习如何通过引用将结构数组传递给从first function 中调用/执行的second function。我的目标是从second function only 修改/更改任意结构的内容。下面的代码有效,但不幸的是,它并没有完全达到我想要实现的效果。我可以访问second function 中的任意结构。换句话说,我想通过在main 中调用/执行first function 来处理for 内的所有结构(使用for 循环)仅一次 并且不使用for 循环。

second function,在下面的代码中,被命名为passByReference_inner

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 */

第一个函数:(passByReference)

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

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

第二个函数: (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;
}

主要:

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

【问题讨论】:

  • 我希望所有的问题都像这样......
  • C语言不能按引用传递,只能按值传递;但是,它可以传递一个指针。
  • 在 main() 中,变量 'cptr' 和所有用法都可以完全替换为对 '&c[i]' 的引用
  • 在 main() 这一行:'cptr[i] = &c[i]' 什么都不做,可以消除
  • 在代码中,数字“12”是出现在代码中多个位置的“神奇”数字。该数字应由#define MAX_COUNT (12) 定义,然后在当前使用“12”的所有地方使用 MAX_COUNT。

标签: c arrays function struct


【解决方案1】:

我认为你想要做的是这个

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

您应该知道c 中的数组在作为参数传递给函数时会衰减为指向其第一个元素的指针。

由于您想处理第二个函数中的所有结构,我认为不需要第一个函数,无论如何您会这样做

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

由于您有效地传递了一个指针,因此您可以直接在第一个和第二个函数中更改它的内容。

还有一点,你并不真的需要static 关键字,特别是在main() 中,static 在函数调用之间保留变量的值,因为main() 通常只会在函数调用中调用一次程序的生命周期...在那里使用static 没有多大意义。

【讨论】:

  • 如果你是通过引用,你为什么要HEAD static
  • 我认为 OP 想要 passByReference_inner 内部的 for 循环。并没有真正改变答案的本质,但需要重新安排一下。
  • @DavidC.Rankin 你把staticconst 混淆了吗?
  • @user3386109 你是对的,我只是重新阅读了这个问题,有时我看不懂英语。
  • 没问题,问题中的措辞让人很难跟踪所有功能,但您的回答很好 +1。
【解决方案2】:

你的第二个函数是正确的。

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

你应该做的是

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

因此,您将传递指向数组第一个元素的指针,以及数组中元素的数量,如下所示:

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

这会将指向c 数组的第一个元素的指针和数组中的元素数传递给passByReference_inner()。 sizeof(c) 是整个数组的大小,以字节为单位。 sizeof(c[0]) 是数组中元素的大小。因此,例如,如果每个结构的长度为 10 字节(仅作为示例),并且您有一个由 12 个结构组成的数组,则整个数组的大小为 120 字节,这样计算的值是 120/10=12,则数组中的元素数量,自动。

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

在您的函数中,您可以通过以下方式使用数组:

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

将整数 n 添加到指针会使指针前进到数组的下一个 nth 元素。向指针添加整数值不会使指针前进这个字节数,而是指针指向的对象中的字节数乘以您要添加的数字(或减去相同的数字)。这使得指针算术做正确的事。

【讨论】:

  • “当你使用一个数组对象的名字时,在 C/C++ 中它会自动变成一个指针” 在 C++ 中,只有在需要指针的上下文中。您可以将指针或引用传递给给定大小的数组。 (在 C 中,指向数组的指针似乎确实绑定到任何旧指针。我不确定这是标准还是编译器扩展。)
  • @juanchopanza 这个问题没有 C++。 “似乎绑定到任何旧指针”应该是什么意思?
  • @iharob 我指的是这个答案中的一个句子,其中提到了“C/C++”(这可能表明它适用于两种语言,因为没有混合 C/C++ 语言)。至于“......任何旧指针”,我的措辞很差,但似乎在 C 中你可以说int (*p)[2] = &amp;a; 其中aint。在 C++ 中,a 必须是 int[2]
  • @juanchopanza 不,你不能,在 C 中 a 也必须是 int[2]。您可以肯定地编译它,但至少gcc 会发出警告。关于 C/C++ 的事情,是的,我在答案中看到了,对不起。
  • @iharob 我不确定细节,但至少 clang 会在 C++ 中发出一个错误,并且在 C 中只有一个警告(我记得最近版本的 gcc 的行为方式相同。)我的理解是实现必须在 C++ 中发出错误。无论如何,我对所讨论句子的观点是成立的。
【解决方案3】:
  • 以下代码编译干净。
  • 以下代码移动增量值循环
    到 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】:

    我分析了所有三个解决方案(iharob、user3629249、Sam Varshavchik)并得出结论,Sam Varshavchik 和 iharob 的第二个解决方案是正确的。第一个 iharob 的解决方案和 user3629249 的解决方案本质上是相等的。他们将for 循环从main 移动到first function。 iharob 帖子的第二个解决方案与初始帖子的要求相匹配。山姆的解决方案给了我足够的提示/说明'如何将for循环从主循环移动到second function(基本上,我不知道该怎么做,因此寻求帮助)。

    所以,长话短说,这里是实现几乎所有贡献者的所有建议的源代码。代码编译干净,所以,像我这样的初学者,可以照原样学习,了解一些关于指针指针、指针算法和结构数组的细节。

    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(第一个函数)

    #include <stdio.h>
    #include "array_of_struct.h"
    
    void passByReference(HEAD **c, size_t n)
    {
        passByReference_inner (*c, n);
    }
    

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

    ma​​in.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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-06
      • 1970-01-01
      • 1970-01-01
      • 2021-11-02
      • 2019-06-22
      • 2019-05-03
      相关资源
      最近更新 更多