如何将局部结构传递给函数?

时间:2018-07-27 17:35:57

标签: c scope sdl pass-by-reference sdl-2

以下链接说,在main中定义的结构没有函数调用的范围,因为它们是局部的,因此您应该全局定义结构。但是,对于变量,最好在本地声明变量并使用指针传递给函数,而不是声明全局变量。

在纯C中是否有使用指针等的方式将main中定义的结构传递给函数?如果您不介意,请使用示例程序来演示该方法。谢谢。

where to declare structures, inside main() or outside main()?

此代码有效,但不是我想要的。我想在main中定义结构。这可能吗?

#include <stdio.h>
#include <SDL2/SDL.h>

void function();

struct hexColour
    {
        Uint32 red;
    }hc;

int main(void)
{
    hc.red = 0xFFFF0000;
    function(hc);
    return 0;
}

void function(struct hexColour hc)
{
    printf("red is %x\n", hc.red);
}

我想要的是:

int main(void)
{
    struct hexColour
    {
        Uint32 red;
    }hc;
    hc.red = 0xFFFF0000;
    function(hc);
    return 0;
}

5 个答案:

答案 0 :(得分:4)

首先,您应该真正使用与函数定义匹配的适当原型。

第二,您的示例 do 将结构传递给函数中的局部变量hc

运行function时,内存中有两种不同的结构:main函数中的结构和function函数中的局部结构。


为了说明我的基础,以下是可能会问到的另外两个问题的两个答案:

  1. 您想在main函数中定义结构本身,然后在其他函数中使用它。

    类似

    int main(void)
    {
        struct hexColor
        {
            uint32_t white;
            // Other members omitted
        };
    
        struct hexColour hc;
        hc.white = 0xff;
    
        func(hc);  // Assume declaration exist
    }
    
    void func(struct hexColour my_colour)
    {
        printf("White is %u\n", my_colour.white);
    }
    

    不可能hexColour结构仅在main函数内部定义。没有其他功能可以使用该结构。不管是否传递指针都没有关系,结构hexColour仍然只存在于main函数内部。

  2. 通过将指针传递给结构对象来模拟传递引用。喜欢

    struct hexColor
    {
        uint32_t white;
        // Other members omitted
    };
    
    int main(void)
    {
        struct hexColour hc;
        hc.white = 0xff;
    
        // Assume declaration of function exists
        func(&hc);  // Emulate pass-by-reference by passing a pointer to a variable
    }
    
    void func(struct hexColour *colourPointer)
    {
        colourPointer->white = 0x00;
    }
    

    之所以可以使用 ,是因为在全局范围内,结构hexColour存在于main函数之外。在结构定义之后声明和定义的所有函数都可以使用该结构及其成员。

答案 1 :(得分:1)

如果按值传递,则会进行复制(昂贵,修改不会反映在外部)。如果只想传递一个指向struct的指针,,但这并不意味着您要通过引用传递struct(C没有引用),那么您就是在传递指向按值指向struct的指针

void function(struct hexColour* hc) {
  printf("red is %x", hc->red);
}

int main() {
  ...
  functon(&hc);
  ...
}

请参阅:

  • 该函数的签名从struct hexColor变为struct hexColor*,以便您传递指针(按值)
  • 要在处理指针时访问struct的字段,请使用->而不是.
  • 调用函数时,您需要将地址带到结构,function(hc)变成function(&hc)

现在,由于您要传递地址,因此该结构将对实际值进行任何修改。

答案 2 :(得分:1)

您似乎对链接的问题及其答案不完全理解。你写,

  

以下链接说main中定义的结构没有   函数调用的范围,因为它们是局部的,所以您应该   全局定义您的结构。

这里的歧义是在结构类型(例如您的{{1})和具有这些类型的对象(例如您的struct hexColour)之间。应该声明struct类型和struct对象,以便它们在需要它们的所有地方都处于范围内,但是对于这两种不同类型的实体以及在不同的情况下,它们的作用不同。

  

但是对于变量,最好在本地声明变量   并通过引用传递而不是声明全局变量。

通常最好使用块范围变量而不是文件范围变量,是的,但是C仅按值传递,不按引用传递。在很多情况下,通过指针(按值)传递指针而不是它们指向的对象是有利的,并且这几乎是通过引用传递的,但是肯定没有规则或一般惯例认为传递指针普遍比传递指针要好将它们指向的对象传递出去。

  

在那里   在纯C中使用指针等将本地结构传递给   功能?

主叫方和被叫方都必须就每个参数的类型达成共识,并且有很多方法可以实现此目的。但是,随着C的发展,存在一些约定,这些约定涉及如何有效地解决诸如此类的问题。其中很大的是:

  • 要在多个翻译单元中使用的任何函数和任何非内置类型都应在头文件中声明,并且该头文件应包含在每个需要它的翻译单元中。

这是您根据“全局”定义提出的规则的概括。示例:

colour.h

hc

请注意,类型#ifndef COLOUR_H #define COLOUR_H struct hexColour { Uint32 white; Uint32 black; Uint32 red; Uint32 pink; Uint32 grey; }; // Note that only the type is declared here, not any objects void function(struct hexColour hc); #endif 的声明出现在具有该类型参数的函数struct hexColour的声明之前。 然后,您可以在适当的位置使用这些类型和函数,例如:

main.c

function

请注意,#include "colour.h" int main(void) { struct hexColour hc = { .white = 0xFFFFFFFF, .black = 0xFF000000, .red = 0xFFFF0000, .pink = 0xFFFF9999, .grey = 0xFFA0A0A0 }; function(hc); return 0; } void function(struct hexColour hc) { printf("red is %x\n", hc.red); } 声明是此处定义的一部分,它与标头中的声明匹配。只要调用者有头文件告诉它如何声明该函数,就可以在另一个源文件中轻松定义该定义function。您可以根据需要function()将coulour.h转换为许多不同的源文件。

但是请注意,在这种情况下,该结构按值传递。这是定义明确且完全可以接受的,但是由于该函数仅接收一个副本,因此无法影响对调用者原始副本的更改。如果希望函数能够执行此操作,则需要将指针传递给结构(按值),而不是结构本身:

#include

答案 3 :(得分:1)

您可以采用本地定义的结构并将其传递给另一个函数:

void f1(struct s);

int main()
{
    struct s s1;
    f1(s1);
}

您可以采用本地定义的结构并将其指针传递给另一个函数:

void f2(struct s *);

int main()
{
    struct s s2;
    f2(&s2);
}

您可以返回本地定义的结构:

struct s f3()
{
    struct s ret;
    /* ... */
    return ret;
}

您可以指针返回到本地定义的结构:

struct s *f4()
{
    struct s ret;
    /* ... */
    return &ret;     /* WRONG */
}

如果在函数中声明结构,则它不是全局变量,因此无法在未传递结构或指针的另一个函数中引用它:

void f5();

int main()
{
    struct s s1;
    f5();
}

void f5()
{
    int x = s1.field;    /* WRONG */
}

最后,如果您在函数内部声明结构类型本身,则会得到无法在其他地方正确引用的结构:

void f1(struct s);

int main()
{
    struct s { int a, b; } s1;
    f1(s1);
}

void f1(struct s arg)    /* error: this struct s might not be the same as the previous one */
{
    int x = arg.b;       /* error: compiler might not know that struct s contains a and b */
}

答案 4 :(得分:0)

看了以前的答案。建议您注意声明和定义之间的“ C”区别。请注意,早期版本的“ C”不允许在堆栈上传递结构的副本,而只能传递指向结构的指针。