在C中共享用于科学计算的通用数据

时间:2018-02-15 12:36:10

标签: c design-patterns dry scientific-computing

在我被迫使用C进行科学计算的作业中(而不是说C ++,我的默认选择),我经常会遇到以下模式:

通常,许多功能通常需要一组数据。例如,在求解微分方程时,我需要知道点的数量,方程式'参数等:

struct parameters{
    unsigned int num_x;
    double length_x;
    // so forth
};

我经常最终必须将它们组合在一个结构中,然后最终在几乎所有函数中重复自己:void f(struct parameters* p, ...)。如果每个函数都将其作为其界面的一部分是有意义的,那就不会那么糟糕,但情况并非总是如此,而且我还是不喜欢重复。

此外,将所有这些参数放在一个结构中并不总是有意义,但将其拆分会使界面更难以管理。

是否有任何变通办法或有用的设计模式来处理这个问题?制作全局p可以解决这个问题,但是在通常不建议使用全局的情况下证明这一点是合理的。

4 个答案:

答案 0 :(得分:5)

在我看来,不使用全局变量有两个重要原因:

  1. 由于他们可以随处访问,因此无法跟踪他们何时以及如何更改。
  2. 它们的使用使得将一些独立代码转换为可以从另一个程序轻松调用的实用程序函数(例如库)变得更加困难,可能有多个实例。
  3. 但有时候,有些数据只是真正的全球性,可能需要在一个项目的所有部分,如果是这样,我不相信应该有任何耻辱,使它成为全球性的,如果基本上

    你可以尽职地传递一个指向你的共享"或"普通"数据(如你所建议的),这通常是正确的模式,但在这种情况下,你基本上重新引入了问题#1。

    如果您确定自己永远不会想要将您的程序重新打包为可分离的,可调用的库,那么异议#2也会消失。

    正如Mark Benningfield在评论中所说,不使用全局变量的原因不仅仅是因为每个人都说你不应该这样做。如果你知道自己在做什么,如果全球不会给你带来问题,你应该继续使用它。

    我,我唯一坚持的是,如果一个变量是全局变量,它必须有一个漂亮的,长的描述性名称。单字符或双字符全局变量名称就在右边。

    (但是所有这些都说明了,你通常会发现像goto这样的全局变量可以保持在最低限度。尽管有这样的建议,一般的建议是尽可能避免它们。事实上,有时过分热心或虔诚地应用,通常是正确的。)

答案 1 :(得分:1)

通常你只是传递一个指针,使用一个大结构可能是prefererd。您可以在函数中记录它使用的成员(实际界面)。

你可以在不同类型的计算的许多结构中分解结构,所有结构都有不同的成员,并且可以将它们全部组合在大结构中。

可能没有首选的设计模式。

答案 2 :(得分:0)

我过去使用的一种方法是在文件级别声明一组宏常量 - 您的示例将类似于

#define NUM_X <value>
#define LENGTH_X <value>

这些当然是由预处理器代替的,它在全球规避的情况下是有益的。

答案 3 :(得分:0)

如果你真的想避免使用全局变量但只想设置一次你的结构,那么你可以编写一个模块来做到这一点。

parameters.h:

struct t_param{
   unsigned int num_x;
   double length_x;
   // so forth
}; 

int get_parameters(struct t_param * out);
int init_parameters(const struct t_param* in);

parameters.c:

#include <string.h>
#include "parameters.h"
static struct t_param parameters = {0,0.0};

static int initialized = 0;

int init_paramaters(const t_param* in)
{     
   if(initialized == 0)
   {
      memcpy(&parameters, in);
      initialized = 1;
      return 0;
   }else
   {
      return -1;
   }  
}  

int get_parameters(t_param *out)
{
   if(initialized == 0)
   {
      return -1;
   }else
   {
      memcpy(out, &parameters);
      return 0;
   }  
} 

修改:将memcpy来电的成员分配。