在其范围之外访问本地声明的结构

时间:2015-01-04 07:27:08

标签: c struct

我想将数据写入结构数组。结构本身在main()中声明和定义。我有3个函数需要编写,处理和读取数组中的数据。 我所能做到的只是创建一个全局结构声明,然后将指针传递给它们。

是否可以不将结构声明设为全局?

相关代码发布在下方。

这是我在main()

之外的结构声明
struct date
{
    int d;
    int m;
    int y;
};
struct stud
{
    int roll;
    char name[30];
    struct date dob;
    int P;
    int C;
    int M;
    float PCM;
    char flag_in;
    char flag_pro;
};

这些是功能定义。

 void getdata(struct stud *S)
    {
        scanf("%d", &(S->roll));
        scanf("%s", (S->name));
        //Similarly for dob, p, c, m
        (S->flag_in)='1';
        return;
    }

void process(struct stud *S)
{
    if(S->flag_in=='1')
    {
        S->PCM=(S->P + S->C + S->M)/3;
        S->flag_pro='1';
    }
}

void display(struct stud *S)
{
    for(int x=0; x<10; x++)
        if(S[x].flag_in=='1')
        {
            //printing the data to the console output
        }
}

这些是函数调用:

getdata(&S[i]);
process(&S[x]);
display(S);

5 个答案:

答案 0 :(得分:1)

你能做的是在main中声明struct。并在调用函数时传递指针:

//this code is inside main
struct stud arr[10]; // create an array for the struct
display(arr); //pass the pointer to function

因为在函数之前调用main,所以数据不会被删除,并且将存在于可以在它们之间传递指针的其他函数的处理中。

虽然我建议不要使用这种方法,如果这些功能不是为了一个目的(更改值,打印等等)。如果数据结构用作全局,则将其声明为全局。

答案 1 :(得分:1)

我的印象是您不清楚struct类型的定义与该类型的实例之间的区别。

为了能够使用struct变量,您的函数必须查看完整类型声明,以便编译器知道变量的结构以及访问不同的字段。但他们没有必要看到变量声明。通过作为参数传递的指针,可以毫无问题地访问该变量。

答案 2 :(得分:1)

完全有效的是不想将程序的其他部分暴露给类型的内部结构。

C非常适合以相当优雅的方式做到这一点。

调用此X.h

//Declaration of X as pointing to an incomplete struct XS.
//This says there's such a thing as a struct XS but not how it is laid out or even how big it is.
//It also says X is a short-hand for a pointer to a mysterious XS structure. 
typedef struct XS* X;

//Creates an X and returns a pointer to it. Remember to call destroyX(.) exactly once - later.    
X createX(void);
//Does something with X and returns some number.
int doXThing(X x);

//Destroys an X. Must be called exactly once for each return value from createX().
void destroyX(X x);

这是prog.c(包含您的main(.)函数)。

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

//Now we actually define that mysterious structure.
//Other translation units will not see this.
struct XS {
    int v;
} ;

//Here we have size and layout so we can actually implement it.

X createX(void){
    X x=malloc(sizeof(struct XS));//Explicit allocation of 'implementation struct'.
    if(x==NULL){
        return NULL;//malloc(.) failed.
    }
    x->v=0;
    return x;
}

int doXThing(X x){
    return (x->v)++;
}

void destroyX(X x){
    free(x);
}

int main(void) {
    X x=createX();

    printf("%d\n",doXThing(x));
    printf("%d\n",doXThing(x));
    printf("%d\n",doXThing(x));

    destroyX(x);

    return 0;
}

请注意,使用#include "X.h"的其他模块不会看到结构的布局。 好处是实现可以正常更改而无需重新编译 - 只需重新链接即可。 缺点是无法访问X的大小和布局,使用&#39;模块需要将所有工作委托给一个模块! 这意味着所有X必须来自免费存储(或实现模块中的静态池)。

这个模型非常普遍且非常强大,因为它允许完全抽象和数据隐藏。

如果你愿意做大量的演员表演,你甚至不需要透露&#39;名称XS

typedef XSHandle* X;

甚至

typedef unsigned short* X; //Little used type...

但是没有被引导进入:

typedef void* X;

在C. void*中,你的演员阵容如此混乱,你会遇到麻烦! 然而,C ++的表现要好得多。

PS:将实施放在与main(.)相同的翻译单元中是不正常的。 在一个小项目中没有错,但在一个小项目中进入相当多的抽象是不正常的。

PPS:声明此方法提供了非常高程度的OO编程。可能有趣的是,Stroustrup制定了文档化的设计决策,不对C ++中的所有类进行此操作,因为它具有固定且不可避免的开销,并且他给自己一个零开销原则&#39;并希望提供一种“混合”的方式。直接访问对象布局的抽象(作为局部变量分配,直接访问成员,内联函数,......)。

我认为他做出了正确的决定,作为C ++预期用途的语言级决策。在适当的情况下,这并不会使它成为糟糕的设计模式。

答案 3 :(得分:0)

  

是否可以不将结构声明设为全局?

不,任何函数都需要struct的定义才能显示(全局),以使其可用。否则,从函数的角度来看,不可见的struct将是一个未定义的标识符。

在函数外的任何地方都不会看到本地结构。

更重要的问题是,在将其置于本地而不是全球时,您会节省多少?我想到的一件事是编译时间可能更快,因为如果在标题中声明全局,很多TU会不必要地看到它。

答案 4 :(得分:0)

如果您的结构位于main()内,那么此结构的范围是main()的本地范围 由于结构是用户定义的数据类型,因此在您尝试时无法使用,因为此新类型仅在main()

中可见

因此,您定义的函数将无法查看结构。

因此,为了处理这个问题,结构应该是全局的。

这是你问题的二元答案

Is it possible without making the structure declaration global?

不是