从函数向全局结构赋值

Assign values to a global struct from a function

提问人:user17850871 提问时间:2/15/2022 最后编辑:Vlad from Moscowuser17850871 更新时间:1/10/2023 访问量:1226

问:

我正在从一本书中学习 C,我尝试了各种东西,以便更好地理解这门语言。 我正在尝试将值从函数传递到全局结构。我遇到了麻烦,因为我执行了一个来查看是否确实传递了这些值,但结果显示不同的值:printf

#include <stdio.h>

void receive_date(); //prototype of the function


struct date_example {
    int day;
    int month;
    int year;
};

int main()
{
    struct date_example d;
    receive_date();
    //this line below shows different values than those provided by the scanf inside the function
    printf("the day is %d and the month is %d and the year is %d",d.day,d.month,d.year); 
    return 0;
}



void receive_date(void)
{
    struct date_example d;
    printf("give day: \n");
    scanf("%d", &d.day);
    printf("give month: \n");
    scanf("%d", &d.month);
    printf("give year: \n");
    scanf("%d", &d.year);
    printf("the date is: %.1d %.1d %.1d \n", d.day, d.month, d.year );
}

结果如下:

give day:
2
give month:
3
give year:
2021
the date is: 2 3 2021
the day is 32758 and the month is 0 and the year is 0  // this is the part that gives different values
Process finished with exit code 0
c 结构 作用域 传递引用 函数定义

评论

3赞 Yunnosch 2/15/2022
没有全局结构,你有两个局部结构。
0赞 n. m. could be an AI 2/15/2022
不建议在实际代码中使用全局变量。

答:

1赞 Vlad from Moscow 2/15/2022 #1

从函数向全局结构赋值

对于初学者来说,您既没有结构类型的全局对象。

在程序中,您有两个具有自动存储持续时间的结构类型的本地对象。这意味着它们在定义它们的范围之外不是活的。

在函数中receive_date

void receive_date(void)
{
    struct date_example d;
    printf("give day: \n");
    scanf("%d", &d.day);
    printf("give month: \n");
    scanf("%d", &d.month);
    printf("give year: \n");
    scanf("%d", &d.year);
    printf("the date is: %.1d %.1d %.1d \n", d.day, d.month, d.year );
}

您初始化了其局部变量,该变量在函数外部不可见且处于活动状态。d

在 main 中,您正在尝试输出未初始化的对象 d 的数据成员

int main()
{
    struct date_example d;
    receive_date();
    //this line below shows different values than those provided by the scanf inside the function
    printf("the day is %d and the month is %d and the year is %d",d.day,d.month,d.year); 
    return 0;
}

因此,代码调用未定义的行为。

您可以通过以下方式更新程序

void receive_date( struct date_example *d );

请注意,在这种情况下,您需要在函数声明之前移动结构定义。

函数 main 将如下所示

int main()
{
    struct date_example d;
    receive_date( &d );
    //this line below shows different values than those provided by the scanf inside the function
    printf("the day is %d and the month is %d and the year is %d",d.day,d.month,d.year); 
    return 0;
}

函数receive_date将定义如下

void receive_date( struct date_example *d )
{
    printf("give day: \n");
    scanf("%d", &d->day);
    printf("give month: \n");
    scanf("%d", &d->month);
    printf("give year: \n");
    scanf("%d", &d->year);
    printf("the date is: %.1d %.1d %.1d \n", d->day, d->month, d->year );
}

评论

0赞 user17850871 2/15/2022
谢谢你解释这部分。正确的方法是什么?
0赞 Vlad from Moscow 2/15/2022
@user17850871 请参阅我附加的帖子。
0赞 user17850871 2/15/2022
it 说: 'receive_date' 的冲突类型
0赞 Vlad from Moscow 2/15/2022
@user17850871 对不起。将结构定义放在函数声明之前。
0赞 user17850871 2/15/2022
谢谢,我点赞了所有的答案,因为它们真的很有帮助。你能告诉我更多关于你的答案吗?您在这里使用了指针,但可能没有指针即可完成。请参阅我留给另一个答案的评论,其中通过在结构定义之后立即添加语句使其在没有指针的情况下工作。我现在开始学习指针,所以在这里看到它们会有所帮助,但要澄清你的答案,更多关于它是如何工作的。
2赞 Yunnosch 2/15/2022 #2

您没有全局结构,即不是全局和结构类型的变量。只有类型声明是“全局”的。

更明确地说,此行有两次,每个函数一次。

struct date_example d;

里面的那个做一个局部变量,只能从 访问。
里面的那个在那里做一个本地的,这是从该函数中提及它的所有行访问的那个。
main()main()receive_date

因此,无论您在内部做什么,都会影响本地的,但不会影响另一个本地的。receive_datemain()

您在该函数中从本地到该函数打印的任何内容都是无关紧要的,并且在 中/从中不可见。dmain()

如果你确实希望在第二个函数中对你所做的任何事情都有一个可见的效果,那么你需要删除这两条相同的行,并在两个函数之外创建一个,即在另一个函数之外和之外。它将定义一个单一的全局,可以从两个函数访问。dmain()main()d

但是,“你需要”仅指您的学习实验。
实际上,不建议使用全局变量进行设计。
您最好使用返回值,或者(可能比现在稍微高级一些)指向变量的指针参数,以便在函数中进行操作。

2赞 ryyker 2/15/2022 #3

这只会创建结构,但不会创建结构变量:

struct date_example {
    int day;
    int month;
    int year;
};

然后,代码在自动空间(局部范围)中定义结构变量:

int main()
{
    struct date_example d;
    ...

}

要使它全局化,只需将此语句放在结构定义之后:

struct date_example {
    int day;
    int month;
    int year;
};

struct date_example d;

然后修改以下内容以使用新的全局...

int main()
{
    //struct date_example d;//already defined in global space
    receive_date();
    ...
}
void receive_date(void)
{
    //struct date_example 'd', already defined in global space.
    printf("give day: \n");
    scanf("%d", &d.day);
    printf("give month: \n");
    scanf("%d", &d.month);
    printf("give year: \n");
    scanf("%d", &d.year);
    printf("the date is: %.1d %.1d %.1d \n", d.day, d.month, d.year );
}


上所述,使用全局变量并不总是最好的方法。尽管全局变量有其位置,但应谨慎使用。考虑将指向结构实例的指针作为替代方法。这是如何...

//assuming same struct definition as before...
//change prototype to accept pointer instance of struct date_example
void receive_date(struct date_example *d);

int main(void)
{
    struct date_example date = {0};//define instance of struct date_example here
    receive_date(&date);//pass address of 'date'
    printf("the date is: %.1d %.1d %.1d \n", date.day, date.month, date.year );
    return 0;//use a return statement to exit program
}

void receive_date(struct date_example *d)
{
    //using pointer argument d
    printf("give day: \n");
    scanf("%d", &d->day);//note change from . to -> for pointer notation
    printf("give month: \n");
    scanf("%d", &d->month);
    printf("give year: \n");
    scanf("%d", &d->year);
    //to illustrate, call printf in main()
    //printf("the date is: %.1d %.1d %.1d \n", d.day, d.month, d.year );
}

评论

2赞 user17850871 2/15/2022
我从 main 和函数中删除了局部变量 d,在 struct 声明下添加了 并且它工作正常。struct date_example d;