2013-05-09 58 views
3

C89 海合会(GCC)4.7.2在函数返回一个静态结构

你好,

我保持某人的软件,我发现这个函数返回一个静态结构的地址。这应该是好的,因为静态会指示它是全局的,所以结构的地址在程序终止之前可用。

DRIVER_API(driver_t*) driver_instance_get(void) 
{ 
    static struct tag_driver driver = { 
    /* Elements initialized here */ 
    }; 

    return &driver; 
} 

像这样来使用:

driver_t *driver = NULL; 
driver = driver_instance_get(); 

驱动变量是整个程序中使用,直到其终止。

一些问题:

  1. 它是很好的做法,以做到这样吗?
  2. 是否有任何区别,声明它在文件级功能之外是静态的?
  3. 为什么不传递一个内存池到函数中,并将内存分配给结构,以便在堆中声明结构?

非常感谢您的任何建议,

+0

这个结构特别大,你会非常关心它的出口? – 2013-05-09 14:48:30

+0

如果结构是只读的,那么函数可能应该返回一个指向“const”结构的指针。另外,什么是'DRIVER_API'? – 2013-05-09 14:56:40

+0

DRIVR_API是#define DRIVER_API(类型)EXTERN_C __declspec(dllexport)类型 – ant2009 2013-05-09 15:45:24

回答

3
  1. 一般来说,没有。它使该功能不可重入。在代码作者真正知道他们在做什么的情况下,它可以用于克制。

  2. 在外面声明它会污染文件级名称空间和结构对象的名称。由于在其他地方不需要直接访问该对象,所以在函数中声明它更合理。没有其他区别。

  3. 分配在堆上?性能会受损。内存碎片会发生。调用者将承担明确释放内存的任务。强制用户在可以避免时使用动态内存通常不是一种好的做法。

    可重用实现的一个更好的想法是将指针从外部传递到目标结构。这样调用者就可以以任何他们认为合适的方式自由分配接收者的内存。


当然,你所看到的在这里可以简单地是一个C实现单例类的成语(最有可能的是,通过该功能的名称判断)。这意味着该函数应该每次都返回相同的指针,即所有的调用者都应该通过返回的指针来查看和共享同一个结构对象。而且,可能的话,你甚至可能会期望修改同一个对象(假设没有并发)。在这种情况下,您在这里看到的是全局变量的函数包装实现。所以,在这种情况下改变任何东西实际上都会挫败目的。

+0

1. ... like *只读* struct/pointer – 2013-05-09 14:52:10

3
  1. 只要你意识到其对由该函数返回的指针的任何代码修改同一个变量为得到相同的指针指的是任何其他代码,它是不是一个巨大的问题。只要'可以是一个相当重要的问题,但它是有效的。它通常不是最佳实践 - 例如,返回指向单个静态变量的指针的C函数(如asctime())并不像将结果放入用户提供的变量那样容易使用 - 尤其是在线程代码中(该功能不可重入)。然而,在这种情况下,它看起来像你正在实现一个Singleton模式;你可能只需要一个'驱动程序'的副本,所以对我来说看起来很合理 - 但是在指出'这是恶魔般的错误'之前,我们需要更多关于用例的信息。

  2. 这里的函数static和文件静态变量之间并没有太大的区别。区别在于实现代码(文件中的静态变量可以被文件中的任何代码访问;函数静态变量只能在一个函数中访问),而不是用户代码中。

  3. '内存池'不是一个标准的C概念。一般来说,通过被调用函数初始化结构可能会更好,但它取决于上下文。就目前而言,为了它的目的而设计,这是可以的。

注:该代码将被更好地写成:

driver_t *driver = driver_instance_get(); 

优化器将可能无论如何优化代码,这一点,但没有点分配NULL,然后立即重新分配。