1

在一个更大的项目中,我要编写一个在相同内存结构上工作的 C 函数列表。由于这些函数在代码的非常不同的部分(以及在单独编译然后链接的不同库中)调用,我想避免必须将指向内存结构的指针作为参数传递给我的每个函数调用。

我正在考虑将内存结构作为静态变量存储在单个函数中,并始终在我的其他函数中调用该函数以获取指向内存结构的指针。在下面的示例中,我使用storage()来设置sto指针。

我测试了下面的代码,它似乎工作正常。这是标准方法吗?我有什么风险?这会一直有效吗?更好的解决方案?

我的函数没有并发调用。当然,我也应该释放分配的内存。

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

int* storage(int get_set)
{
    static int* sto;
    if (get_set==1)
    {
        sto=malloc(2*sizeof(int));
        sto[0]=1;
        sto[1]=2;
    }
    printf("storage: content = %d %d, pointer= %d\n", sto[0], sto[1], sto);
    return sto;
}

void add11()
{
    int* sto =storage(0);
    sto[0]+=1;
    sto[1]+=1;
    printf("add11: content = %d %d, pointer= %d \n", sto[0], sto[1], sto);
}

void multo0()
{
    int* sto =storage(0);
    sto[0]=sto[1]*sto[0];
    sto[1]=0;
    printf("multo0: content = %d %d, pointer= %d\n", sto[0], sto[1], sto);
}


int main(void) {
    storage(1); // initialize memory only once
    add11();  // work on memory 
    multo0();
    add11();
    // ...
    return 0;
}

我想要这样的原因如下:

我正在编写的函数集执行图像增强的单独和辅助可选任务,并以不同方式从先前观察到的图像中学习。 sto存储此学习和参数化选项的内存。

在整个项目中,我的函数将在多个嵌套函数调用中调用。作为参数传递sto意味着在项目的主体中声明一个指针并更改大量与我的函数执行的任务无关的核心嵌套函数以传递附加参数。

此外,同一组功能将集成到多个略有不同的项目中,因此侵入性较小的集成,必须尽可能少地修改外部代码,将是一个加分项。

对于可读性问题,所有且只有访问共享内存的函数具有相同的前缀。我知道这不是完整的解决方案,但我相信它增加了一点可读性。

除了更改所有功能以在项目周围进行之外,是否还有其他选择sto

4

3 回答 3

2

这有几个缺点

首先,您的函数在每次调用时都会分配内存,但从函数名称中不清楚调用者需要显式释放返回的内容。

其次,它充当全局值,最好使用指针在函数之间传递数据,因为它更清楚 - 从可读性的角度来看 - 哪个函数通过查看函数原型来访问数据:

void foo(storage* p);
void foo1();
void foo2(const storage* p);

第三,您在访问数据时增加了开销

您的存储函数中也存在内存泄漏,您将 sto 声明为静态,但在将其分配给 malloc 之前不要检查它是否已经指向某个东西。

static int* sto;
if (get_set==1)
{
    sto=malloc(2*sizeof(int));
    sto[0]=1;
    sto[1]=2;
}

应该是这样的

static int* sto;
if (get_set==1)
{
    if ( sto != NULL ) 
    {
      free(sto);
    }
    sto=malloc(2*sizeof(int));
    sto[0]=1;
    sto[1]=2;
}

如果您仍然坚持使用这种方法,您至少应该将值放在一个结构中,然后这些值将被复制并且您不需要每次都分配堆(缺点是开销更大)。

typedef struct
{
  int a[2];
} storage_ret;

storage_ret storage(int get_set)
{
    static storage_ret sto;
    if (get_set==1)
    {
        sto.a[0]=1;
        sto.a[1]=2;
    }
    printf("storage: content = %d %d, pointer= %d\n", sto.a[0], stoa.[1], &sto);
    return sto;
}
于 2013-10-03T08:37:28.743 回答
2

由于您已经将多个模块链接在一起,因此“更标准”的方法是拥有一个静态(单个模块私有)变量(第一种方法),如果您需要访问器函数,请返回一个指向该变量的指针。但是如果访问器只是返回一个指向它的指针,您可以简单地使用“extern”并以自然的方式访问数据(第二种方法)。

第一种方法:

包含数据的模块:

static int mydata; /* note: "static" */

int* accessor() {
    return &mydata;
}

使用数据的模块:

int* accessor();

int main() {
    int* foo = accessor();
}

第二种方法:

包含数据的模块:

int mydata; /* note: no "static" */

使用数据的模块:

extern int mydata; /* note: "extern" */

int main() {
    int* foo = &mydata;
}

第二种方法是“更多 C-ish”并且速度更快。请注意,通常的方法是在第二种情况下简单地使用“mydata”,就好像它是一个普通的局部变量一样,而不是仅仅为了指针而引入指向它的指针——我在这里这样做是为了与第一种情况保持一致。

于 2013-10-03T08:45:31.753 回答
0

这当然不是标准做法,并为您的代码增加了一定程度的可读性问题。想象一下刚刚添加到您的项目中的人现在需要使用此代码,他/她会非常困惑。此外,每个函数调用都可能导致一些开销,因此最好将指针传递给所有函数。

于 2013-10-03T08:34:00.640 回答