全局变量和返回C函数中的多个可变长度数组(指针)

我有一些编程经验,但对C没什么用。

我有一个相当大的C文件。 在其中有多个函数按顺序执行 – 因此在这种特殊情况下,实际上没有函数被调用两次,它们被分解以便于阅读,因为每个函数仍然有一个单独的目的。

这个程序对几个长度可变的double数组进行了大量的计算,因此它们都是指针。 两个问题:

1)从开头计算一次然后作为许多后续函数的输入的变量 – 我应该在这个文件中使它们成为全局变量吗? 根据我在高级语言编程的经验,全局变量并不好。 这不是C的情况,为什么?

2)当我的函数中的一个想要返回多个指针(例如,每个指向一个长度为n的双数组)时,请说double * p1,double * p2,double * p3是相关的,我可以将它们组合成一个结构:

struct pointers { double *p1, *p2, *p3; } ptr; 

foo1将输入double *作为输入,并计算ptr-> p1,ptr-> p2,ptr-> p3,然后ptr将作为foo2的输入。 我应该写吗?

 struct pointers *foo(double *input) 

要么

 void foo1(double *input, struct pointers ptr) 

要么

 void foo1(double *input, struct pointers *ptr) 

为什么C函数通常是’void’函数,除非它只返回一个int或double变量? 输入和输出都作为参数 – 是否令人困惑?

我应该在foo1内部或外部初始化ptr-> p1,ptr-> p2,ptr-> p3?

请注意,foo()是将按顺序调用foo1,foo2的主函数。

回答问题

1)它实际上取决于数据的sizescope 。 如果在函数中有少量用作计算的一部分,则在函数内初始化它更有意义,从而将其范围限制在函数内。

如果数据大小是几兆字节甚至超过几十千字节,那么使用malloc在堆上进行分配是有意义的。

您可以在文件中包含全局变量,但是您必须担心同步对它们的访问 – 谁正在修改它们以及按哪种顺序 –

回答问题2)编写函数签名的更好方法是

 struct { double output1; double output2; double output3; } output_t; 

和函数签名为:

 ReturnCode foo ( double input , struct output_t * output); 

其中ReturnCode可以是just和int值,表示操作是成功还是失败。

1-在C中也非常不鼓励全局变量。 这有两个重要原因:

  • 大多数情况下,您不需要在整个程序中提供变量,因此您实际上不需要将变量设置为全局变量。
  • 使用局部变量,您的代码将更易于维护,并且您将避免可能的副作用 。

但是在你的情况下,正如你所说的ptr.p1, ptr.p2, ptr.p3将成为许多其他后续函数的输入,可能是让它成为全局的更好的决定。 在这种情况下,如果要定义全局(仅在该文件中),则应尝试使用static修饰符。 在这里你可以阅读静态(它可以有2种不同的含义)

我认为你的第二个问题“输入和输出都是参数 – 是否令人困惑?” 它实际上取决于开发人员,语言为您提供了两种选择,但这取决于您制作清晰的代码。

C中也不建议使用全局变量。 我可以从你的问题中收集的是foo1将使结构和foo2将其作为输入。

所以在我看来你应该让foo1返回结构,然后将整个结构作为参数传递给foo2

特别是在C中,强烈建议不要使用全局变量,除非您正在处理每个必须存储其数据的多个文件。 在结构中对数据进行分组并将它们传递给函数要容易得多,这使得整个事情变得清晰易懂

这是我编写的代码示例,它涉及使用结构。 只有函数的声明在这里,但你明白了

 struct elem { void *data; struct elem *next; }; struct binky { struct elem *root; int elem_size; }; void Initialize(struct binky * b, int elem_size); int add(struct binky * b, const void * data); void *get(const struct binky * b, const void * data); void freeMap(struct binky * b);