在没有多态的情况下优化C代码大小

时间:2019-01-28 21:29:39

标签: c

我已经在该站点以及其他地方阅读了有关C语言中的多态性的信息,大多数评论家都不愿意这样做,或者建议改用C ++。我的结构和例程彼此非常相似,只是成员和参数类型不同。这是代码:

h个文件:

typedef struct {
  double *array;
  size_t used;
  size_t size;
} dArray;
void init_dArray(dArray *a, size_t initialSize);
void insert_dArray(dArray *a, double element); 

typedef struct {
  char** array;
  size_t used;
  size_t size;
} sArray;
void init_sArray(sArray *a, size_t initialSize);
void insert_sArray(sArray *a, char* element); 

typedef struct {
  int* array;
  size_t used;
  size_t size;
} iArray;
void init_iArray(iArray *a, size_t initialSize);
void insert_iArray(iArray *a, int element); 

void free_dArray(dArray *a);
void free_sArray(sArray *a);
void free_iArray(iArray *a);

c文件:

void init_dArray(dArray *a, size_t initialSize) {
  a->array = (double *)malloc(initialSize * sizeof(double));
  a->used = 0;
  a->size = initialSize;
}

void init_sArray(sArray *a, size_t initialSize) {
  a->array = (char**)malloc(initialSize * sizeof(char*));
  a->used = 0;
  a->size = initialSize;
}

void init_iArray(iArray *a, size_t initialSize) {
  a->array = (int *)malloc(initialSize * sizeof(int));
  a->used = 0;
  a->size = initialSize;
}

void insert_dArray(dArray *a, double element) {
  if (a->used == a->size) {
    a->size = (a->size*3)/2+8;
    a->array = (double *)realloc(a->array, a->size * sizeof(double));
  }
  a->array[a->used++] = element;
}

void insert_sArray(sArray *a, char* element) {
  if (a->used == a->size) {
    a->size = (a->size*3)/2+8;
    a->array = (char**)realloc(a->array, a->size * sizeof(char*));
  }
  a->array[a->used++] = element;
}

void insert_iArray(iArray *a, int element) {
  if (a->used == a->size) {
    a->size = (a->size*3)/2+8;
    a->array = (int*)realloc(a->array, a->size * sizeof(int));
  }
  a->array[a->used++] = element;
}

void free_dArray(dArray *a) {
  free(a->array);
  a->array = NULL;
  a->used = a->size = 0;
}

void free_sArray(sArray *a) {
  free(a->array);
  a->array = NULL;
  a->used = a->size = 0;
}

void free_iArray(iArray *a) {
  free(a->array);
  a->array = NULL;
  a->used = a->size = 0;
}

主要:

#include <stdlib.h>
#include <stdio.h>
int main(void)
{
        iArray a;
        init_iArray(&a,5);
        for(int i=0; i<10; i++)
                insert_iArray(&a, i+1);
        for(int i=0; i<10; i++)
                printf("%d\n", a.array[i]);
        free_iArray(&a);
        exit(0);
}

是否可以通过减少或减少多态来减少代码大小?

1 个答案:

答案 0 :(得分:2)

您可以简单地抽象元素的类型。您的阵列需要知道的是这些元素的大小。您可以采用允许用户通过函数指针提供副本构造函数和析构函数的完整方法,也可以将数组的范围限制为memcpy()个可移动类型。

为纯数据元素提供数组

您只需将元素的大小作为参数添加到数组struct

typedef struct {
  char *array;
  size_t elementSize;
  size_t used;
  size_t size;
} Array;

void Array_init(Array *a, size_t elementSize, size_t initialSize);
void Array_insert(Array *a, const void* element);
const void* Array_at(Array *a, size_t index);
void Array_destruct(Array *a);

所有对数组的索引都只是将索引与给定的元素大小相乘,以对内部char数组进行索引。内部char指针被隐式转换为接口的void指针,该指针又被隐式转换为double指针,或您插入此数组的任何其他类型。

这很好用,只要元素是可复制的即可。如果您的元素需要自己管理内存,则需要以下方法:

为复杂的数据元素提供数组

如果对象在复制时需要执行自定义内容,则需要为用户提供一种手段以提供必要的行为。这是通过函数指针完成的:

typedef void (*Array_callback_copy_construct)(void* this, const void* original);
typedef void (*Array_callback_destruct)(void* this);
typedef struct {
  char *array;
  size_t elementSize;
  size_t used;
  size_t size;
  Array_callback_copy_construct copy_construct;
  Array_callback_destruct destruct;
} Array;

void Array_init(Array *a, size_t elementSize, size_t initialSize, Array_callback_copy_construct copy_construct, Array_callback_destruct destruct);
void Array_insert(Array *a, const void* element);
const void* Array_at(Array *a, size_t index);
void Array_destruct(Array *a);

Array_insert()Array_destruct()方法现在仅使用用户提供的回调函数来复制和销毁数组的元素。

更多高级版本可能还会使用move构造函数回调和/或(move)赋值回调。复制构建+销毁是您所需的最小设置,使用更高级的回调可以实现更好的性能。


第一种方法非常简单,可以在各种应用程序中使用,我会毫不犹豫地使用它。但是,必须清楚地记录使用memcpy()的收获

第二种方法可以在第一种方法失败的情况下工作,但是通常比它值得的麻烦更多。除非您认为它确实是唯一的解决方案,否则请避免使用它。