在几个C模块之间传递大型数组

时间:2017-09-14 12:11:08

标签: c arrays

我在table.c中定义了几个相当大的数组(每个数组大约有1500个成员)。我需要将它们传递给不同的模块和/或提供一种如何更新它们的方法。

我的问题是如何使它最有效,而不是浪费记忆。我的想法是做标准getters/setters。因此,如果get我将拥有公共职能:

void getTable(tableID, *table)

tableID将枚举我想要的女巫表,*table将指向表格。我想只是一个引用被传递,所以表不是"重复"在记忆中。

然后在otherModule.c中我将jsut调用

table *myPointer;
getTable(TableA, myPointerTable).

这是对的吗?

3 个答案:

答案 0 :(得分:2)

  

我在table.c中定义了几个非常大的数组(每个数组大约有1500个成员)。

在目前的笔记本电脑上(拥有数十亿字节的RAM),十几万个数字的阵列并不大,它是一个很小的阵列。今天,大型阵列至少拥有数百万(机器)数字,您最好使用C dynamic memory allocation

(当然,如果数组的每个元素都是一些复杂而繁重的数据结构 - 例如某些bignum - 事情就不同了)

您可以传递一个指针(指向数组,或指向以flexible array member结尾的某些struct)。

BTW,当作为参数传递时,数组会被衰减为指针(通常,calling convention会使某些地址在某些processor register中快速传递。像

这样的东西
extern double bigarray[123456];
foo(bigarray);

不要复制数组(但只传递其地址)。

  

我的想法是做标准的getter / setter。

这可能很好,而且可能更具可读性。

顺便说一句,你可以定义这些吸气剂& setter在公共头文件中起一些static inline函数的作用(适当地#include编辑)。这将使您的代码可读且快速。

答案 1 :(得分:2)

数组表达式"衰变"在大多数情况下指向,所以如果你定义类似

的东西
T humongous[50000]; // for some arbitrary type T

并将其传递给类似

的函数
foo( humongous );

foo收到的只是指向第一个元素的指针,而不是整个数组:

void foo( T *arr ) { ... }

请注意,在函数参数声明的上下文中,T a[N]T a[]被视为与T *a相同 - 它们都将a声明为指针T。基本上,你不能通过值"传递数组。到C.中的函数。

现在,如果您的数组是structunion类型的成员,并且您将该类型的表达式传递给函数,那么您创建函数中整个数组的副本:

struct blah {
  ...
  T humongous[50000];
  ...
} bletch;

foo( bletch );

void foo( struct blah b ) { ... } // b is a full copy of bletch

因此,在这种情况下,您可能希望将指针传递给bletch而不是:

foo( &bletch );

void foo( struct blah *b ) { ... }

答案 2 :(得分:1)

对于较小的程序,Setter / getter可能是个好主意,尽管您可能希望格式为

table_t* getTable (tableID)

但是,这不是OO意义上的纯getter函数,因为您通过指针公开私有数据。此外,重新入侵可能会成为这种方法的一个问题。对于需要在较长时间内维护的较大的专业课程,这不会做。

最佳解决方案是将分配留给调用者。您可以使用 opaque指针间接执行此操作:

table.h

typedef struct table_t table_t; // forward declaration

table_t* table_init (size_t size, /* stuff */);

void table_free (table_t* table);

table.c:

#include "table.h"

struct table_t // this will be unknown to the caller
{ 
  // private, encapsulated data:
  size_t size;
  int data[]; // flexible array member
};

table_t* table_init (size_t size, /* stuff */)
{
  table_t* result = malloc(sizeof(*result) + int[size]);
  if(result == NULL) { /* handle errors */ }

  result->size = size;
  do_something(result->data);

  return result;
}

void table_free (table_t* table)
{
  free(table);
  /* optionally, make the parameter table_t** and set the pointer 
     to NULL after calling free() */
}

caller.c:

#include "table.h"

table_t* table = table_init(n, /* stuff */);

table_do_stuff(table); // either setter/getter or actual algorithm

table_free(table);

这给出了一个合适的设计并允许多个实例,这也解决了重新进入的问题。