【问题标题】:Pointer to const static array指向 const 静态数组的指针
【发布时间】:2017-11-20 12:44:04
【问题描述】:

对于有限域数学,我将相应的加法和乘法表存储为静态类型的整数数组,例如,对于 GF(4/8),我有

static const uint8_t GF4ADD[4][4] = {...};

static const uint8_t GF8ADD[8][8] = {...};

现在,在运行时,程序从配置文件中读取所需的字段大小,并应将相应的表分配给结构指针:

struct obj data {
...
  uint8_t** table_add;
  uint8_t** table_mult;
...
};

switch(order) {
case 4:
  data.table_add = GF4ADD;
  data.table_mult = GF4MULT;
  break;
case 8:
  data.table_add = GF8ADD;
  data.table_mult = GF8MULT;
  break;
}

当然,上述方法不起作用,但它应该让您了解我想要完成的工作。主要问题是我不知道应该声明结构成员的类型,因为表的大小仅在运行时才知道。此外,我不想只使用表的一维索引。

谢谢,汤姆。

【问题讨论】:

  • 听起来你需要研究一下动态分配
  • 如果您想拥有uint8_t *[4] table_add;uint8_t *[8] table_add;,将它们放在联合类型中是否可行?
  • 嗯,是的,当然。但是结构(以及它的成员)是在标头中声明的,并且仅在之后才实例化。所以问题是,我如何在标题中声明它,因为声明类型不知道大小。
  • C 语言在这里是有问题的,因为它不允许您在文件范围内声明可变长度数组 (VLA)。因此,如果您需要一个可以从多个文件访问的具有可变长度数组的结构,您将不得不做一些变通方法。最常见的方法是将数据“分解”成一个维度并计算运行时的索引。这是一个可以接受的解决方案,如果不是“漂亮”的话。 (高效的 C 代码很少是漂亮的。)

标签: c arrays pointers struct


【解决方案1】:

您需要像以前一样使用指针声明它。之后,当您获得order 时,您将能够动态分配所需的内存。


简单示例1(使用指向指针的指针):

struct{
    int ** table_add;
}data;


int main()
{
    unsigned int order;
    scanf("%u", &order);
    // create "order" pointers 
    data.table_add = malloc(order * sizeof(int *));
    // where each pointer points to "order" elements
    for(unsigned int i = 0; i < order; i++)
        data.table_add[i] = malloc(order * sizeof(int));

    // fill with numbers
    int counter = 0;
    for(unsigned int i = 0; i < order; i++)
        for(unsigned int j = 0; j < order; j++)
            data.table_add[i][j] = counter++;

    // read result
    for(unsigned int i = 0; i < order; i++){
        for(unsigned int j = 0; j < order; j++)
            printf("%d ",data.table_add[i][j]);
        printf("\n");
    }
    return 0;
}

简单示例2(分配二维数组):

将第一个示例的开头替换为:

    ...
    unsigned int order;
    scanf("%u", &order);
    // allocate memory for a 2D array
    data.table_add = malloc(sizeof(int[order][order]);
    // fill with numbers 
    ...

正如@Lundin 提到的,这种方式更有效。在我看来,原因有 3 个:

  1. 大小 - 无需为指针分配内存(保存order * sizeof(int*)
  2. 时间 - 一次呼叫malloc 而不是order + 1
  3. 更简单的代码(更少的mallocs --> 更少的frees --> 更少的错误)

在您的情况下,您需要循环填充元素(循环遍历每个元素并分配它们,或者循环遍历 order 元素并使用 memcpy

【讨论】:

  • 请注意,这不是二维数组,也是非常低效的代码,见Correctly allocating multi-dimensional arrays
  • 当然。但我想这就是 OP 的想法。我将向 malloc 二维数组添加选项,但我认为这是基本的简单答案(毫不奇怪,效率低下)。
  • 4.数据缓存友好(主要性能原因) 5. 堆碎片友好。
  • 但请注意,您不能使用指针指向 2D 数组。 data.table_add = malloc(sizeof(int[order][order]); 将不起作用,除非 table_add 的类型为 int(*)[order]int(*)[order][order]
  • 感谢您的所有 cmets。这是非常有见地的,因为我没有意识到这一点,而且似乎并不是那么简单。假设我忘记了使用先前声明的结构的限制,而只是想创建一个具有连续分配内存的二维数组。在这种情况下,我可以定义 int(*a)[order]; a = malloc(sizeof(int[order][order])) 但是,VLA 然后分配在堆栈上,不是吗?任何数组通常都是这种情况。假设订单真的很大,那我该怎么做呢?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-04
  • 2021-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-14
相关资源
最近更新 更多