从全局变量填充整数数组,然后从C中的函数返回它

时间:2014-04-30 01:02:41

标签: c arrays

有许多全局变量,例如someglobalvalue1,someglobalvalue2等,它们是从我正在处理的应用程序的不同部分动态更新的。在我目前正在处理的部分中,我需要将这些变量收集到整数数组中。因为在不同的组中有很多这些变量,所以我有单独的函数,如GetGroupOne(),GetGroupTwo()等,将全局变量插入数组并将其返回到main函数。我正在使用此页面作为如何从函数返回int数组的指南:http://www.tutorialspoint.com/cprogramming/c_return_arrays_from_function.htm

例如:

int main() {
   int *array;
   array = GetGroupOne();
   /* do stuff with array */
   return 0;
}

int * GetGroupOne() {
  static int array[GROUP_ONE_LENGTH] = { someglobalvalue1, someglobalvalue2, someglobalvalue3 };

  return array;
}

所以,试图编译它(顺便说一下,我只限于C90编译器)给我这个错误:

尝试使用const

初始化变量时出错“初始化元素不是常量”

所以,我确实找到Error "initializer element is not constant" when trying to initialize variable with const和其他似乎暗示我试图做的事情,使用全局变量初始化的线程是不可能的。所以我咬了一下子弹,然后做了这件事:

int * GetGroupOne() {
  static int array[GROUP_ONE_LENGTH];
  array[0] = someglobalvalue1;
  array[1] = someglobalvalue2;
  array[2] = someglobalvalue3;
  /* etc... */

  return array;
}

现在,这个有效但它非常丑陋,看着它会伤害我的灵魂。特别是因为有多个组,其中一些有超过一百个条目,所以我必须分别将每个全局插入到数组中。我知道如何在更高级别的语言中处理这个问题,但C对我来说仍然有点神秘。但我认为必须有一些更好的方法来处理这个问题。任何人都可以朝着正确的方向推动我吗?

谢谢。

2 个答案:

答案 0 :(得分:2)

抛开我自己的灵魂而不是需要数百个全局变量的设计,至少有一种方法可以使用带有可变长度参数列表的函数来改善实现的外观。它看起来像这样(未经测试):

  #include <stdarg.h>
  int * CompileIntegerArray( int *dest, unsigned int count, ... ) {
    int *put = dest;
    va_list arglist;
    va_start( arglist, count );
    for( ; count != 0; --count ) {
      *put++ = va_arg( arglist, int );
    }
    va_end( arglist );
    return dest;
  }

...

  int * GetGroupOne() {
    static int array[GROUP_ONE_LENGTH];
    return CompileIntegerArray( array, GROUP_ONE_LENGTH,
      someglobalvalue1, 
      someglobalvalue2, 
      someglobalvalue3 
      );
  }

要意识到你正在做的事情有可怕的事情。至少,每当组更改长度时,您必须更新长度并确保在调用CompileIntegerArray时输入正确数量的变量,否则可能会将延迟堆栈炸弹引入代码。

这种方法当然会产生一些(次要的)性能影响,而且有些编译器可能会阻塞函数调用的数百个参数。

[已编辑添加替代方案]

你可以做的另一件事就是改善外观并且仍然可以更容易地改变数组元素的顺序。它有点快,并且不依赖于单独的函数来处理数组。这也将使您有机会进行一些错误检查。使用预处理器:

#define _el(x) array[ index++ ] = x;

int * GetGroupOne() {
  static int array[GROUP_ONE_LENGTH];
  int index = 0;

  _el( someglobalvalue1 )
  _el( someglobalvalue2 )
  _el( someglobalvalue3 )

  if( index != GROUP_ONE_LENGTH ) {
    puts( "GAAK!" );
    exit(1);
  }
  return array;
}

答案 1 :(得分:0)

一个选项是使静态数组包含指向全局变量的指针( 计为编译时常量):

int **get_group_one(void)   // (void) instead of () is important
{
// note the `const`, your system will love you for it
// could also add a compile-time test that you actually do have GROUP_ONE_LENGTH entries
static int *const array[GROUP_ONE_LENGTH] = { &global0, &global1, &global2 };

    return array;
}

然后通过宏

访问您的全局变量
#define G1(n) ( *(get_group_one()[n])  )

您可以添加一些错误检查以避免范围错误的未定义行为,如果您尝试G1(n) n超出范围,那么您要么访问虚拟变量,要么调用错误处理程序等

如果您的编译器支持内联函数,那么它将比宏更整洁。

BTW是否有任何理由你不能让你的全局变量首先在数组中?