通过引用传递结构,而不是在void函数中传递值

时间:2018-07-03 21:40:35

标签: c pointers data-structures

我正在尝试使用结构和功能创建联系人列表。目前,我的代码可以编译,但是结构的成员并未像我想做的那样在函数外部被修改。这是我的代码(删除了一些行的长度)

#include <stdio.h>
#include <stdlib.h>

struct ContactInfo
{
    char fname[50];
    char lname[50];
};

struct ContactInfo gc;

void getContactInfo(struct ContactInfo gc)
{
    printf("First Name: ");
    scanf("%s", gc.fname);

    printf("\nLast Name: ");
    scanf("%s", gc.lname);
}

void showContactInfo(struct ContactInfo gc)
{
    printf("* First Name: %s \n", gc.fname);

    printf("* Last Name: %s \n", gc.lname);
}

int main()
{
    getContactInfo(gc);

    showContactInfo(gc);

    return 0;
}

3 个答案:

答案 0 :(得分:2)

执行此操作的C方法只是普通的旧指针:

void showContactInfo(struct ContactInfo* gc)
{
    printf("* First Name: %s \n", gc->fname);

    printf("* Last Name: %s \n", gc->lname);
}

除了必须使用箭头运算符->来访问属性外,其他基本相同。

C本身没有像C ++那样的引用。

答案 1 :(得分:1)

getContactInfo函数应该返回值,但是您可以传入值。

从函数中获取数据的最自然的方法是使用返回值。另外,您不应使用全局变量来传递数据。代码如下:

struct ContactInfo getContactInfo(void)
{
    struct ContactInfo g = { 0 };  // ensure no garbage in case input fails

    printf("First Name: ");
    scanf("%49s", g.fname);

    printf("Last Name: ");
    scanf("%49s", g.lname);

    return g;
}

main中的代码为:

struct ContactInfo gc = getContactInfo();
showContactInfo(gc);

答案 2 :(得分:1)

对于getContactInfo,您需要将指针传递给struct:

void getContactInfo( struct ContactInfo *gcptr )
{
  printf("First Name: ");
  scanf("%s", gcptr->fname);

  printf("\nLast Name: ");
  scanf("%s", gcptr->lname);
}

由于您要修改内容gc,因此需要将指向它的指针传递给函数。请记住,C按值传递所有参数,因此被调用的函数将创建一个单独的重复对象,该对象接收参数的值。您的代码正在修改该重复的对象,这对实际参数没有影响。

当操作数是指向->struct类型的指针时,将使用union运算符-在访问特定成员之前隐式取消引用该指针。等效于写(*gcptr).fname(*gcptr).lname,但眼神上要容易一些。

您将此函数称为

getContactInfo( &gc );

对于showContactInfo,由于您没有尝试修改参数,因此可以保留原样。但是,许多人喜欢传递指向struct的指针以节省内存(您不是在调用的函数中构建struct的副本)。如果要使用指针,我建议像这样使用const关键字:

void showContactInfo( const struct ContactInfo *gcptr )
{
  printf("* First Name: %s \n", gcptr->fname);
  printf("* Last Name: %s \n", gcptr->lname);
}

如果我尝试修改const函数中指向的对象gcptr的内容,则showContactInfo关键字告诉编译器对我大喊大叫。就像上面的getContactInfo一样,您称其为

showContactInfo( &gc );

请注意,我将参数名称更改为gcptr只是为了帮助区分函数定义中的形式参数和函数调用中的实际参数。我通常不喜欢在变量或参数名称中放入任何类型的信息,但是您可以使用任何喜欢的命名约定。