【问题标题】:User defined types with dynamic size in CC中具有动态大小的用户定义类型
【发布时间】:2014-08-26 06:16:13
【问题描述】:

我想定义一个由用户输入大小的数组组成的新数据类型。例如,如果用户输入 128,那么我的程序应该创建一个新类型,它基本上是一个 16 字节的数组。这个结构的定义需要是全局的,因为此后我将在我的程序中使用该类型。有必要为这种结构设置一个动态大小,因为我最终将拥有一个由该类型变量填充的庞大数据库。

我现在的代码是:

struct user_defined_integer;
.
.
.
void def_type(int num_bits)
{
    extern struct user_defined_integer 
    {
             int val[num_bits/sizeof(int)];
    };

return;

}

(不工作)

我发现,最接近我的问题的是: I need to make a global array in C with a size inputted by the user (这没有帮助)

有没有办法做到这一点,以便在整个文件中识别我的结构?

【问题讨论】:

  • 上面的代码无法编译,函数内定义的结构具有局部作用域;不是没有工作。
  • 行不通。使用 malloc 和长度字段。
  • 注意,除法的结果需要向上取整或确保num_bits能被sizeof(int)整除,否则将没有空间存储最后一位

标签: c arrays dynamic-arrays user-defined-types


【解决方案1】:

做的时候:

extern struct user_defined_integer 
{
         int val[num_bits/sizeof(int)];
};

你应该得到警告:

warning: useless storage class specifier in empty declaration 

因为你有一个空的声明。 extern 不适用于user_defined_integer,而是适用于它之后的变量。其次,这无论如何都行不通,因为包含可变长度数组的结构不能有任何链接。

error: object with variably modified type must have no linkage

即便如此,可变长度数组在声明时分配存储空间。您应该改为选择动态内存。

#include <stdlib.h>

typedef struct
{
    int num_bits;
    int* val;
} user_defined_integer;

void set_val(user_defined_integer* udi, int num_bits)
{
    udi->num_bits = num_bits;
    udi->val = malloc(num_bits/sizeof(int));
}

【讨论】:

    【解决方案2】:

    您需要的是 VLA 成员,正如有关 here 的问题。基本上,你声明一个struct,其中包含一个大小字段和一个元素的存储价值作为最后一个成员,然后过度分配它。

    从那个问题导入:

    typedef struct Bitmapset {
        int nwords;
        uint32 words[1];
    } Bitmapset;
    
    Bitmapset *allocate(int n) {
        Bitmapset *p = malloc(offsetof(Bitmapset, words) + n * sizeof *p->words);
        p->nwords = n;
        return p;
    }
    

    【讨论】:

    • 灵活的数组成员是实现这一目标的一种更简洁的方式。
    • 在 C99 中,是的。在此之前,你别无选择,只能溢出一个长度的数组。
    【解决方案3】:

    我想定义一个由用户输入大小的数组组成的新数据类型。例如,如果用户输入 128,那么我的程序应该创建一个新类型,它基本上是一个 16 字节的数组。

    这在 C 中是不可能的,因为 C 类型是 compile-time 的东西,在 run-time 根本不存在。

    但是,对于符合 C99 的编译器,您可以使用灵活的数组成员。您需要一个 struct 包含一些成员并以没有任何给定维度的数组结尾,例如

    struct my_flex_st {
       unsigned size;
       int arr[]; // of size elements
    };
    

    这是一种分配方式:

    struct my_flex_st *make_flex(unsigned siz) {
      struct my_flex_st* ptr 
        = malloc(sizeof(struct my_flex_st) + siz * sizeof(int));
      if (!ptr) { perror("malloc my_flex_st"); exit(EXIT_FAILURE); };
      ptr->size = siz;
      memset (ptr->arr, 0, siz*sizeof(int));
      return ptr;
    }
    

    一旦你不再使用它,别忘了free它。

    当然,您需要在代码中使用指针。如果您真的想要一个全局变量,请将其声明为例如

    extern struct my_flex_st* my_glob_ptr;
    

    【讨论】:

      【解决方案4】:

      试试这个方法-

      #include<stdio.h>
      #include<stdlib.h>
      #include<limits.h>
      struct user_defined_integer
      {
              int *val;
      }user_int;
      void memory_allocate(int num_bit)
      {
              int result;
              result = (num_bit+CHAR_BIT-1)/CHAR_BIT; // since 8 bit =1 byte
              user_int.val=malloc(result*sizeof(int));
              if(user_int.val == NULL){
              printf("Failed to allocate memory\n");
              return ;
              }
              else
              printf("Allocated %d bytes for val\n",result);
      }
      int main()
      {
              int num_bit;
              printf("Enter the number of bits\n");
              scanf("%d",&num_bit);
              memory_allocate(num_bit);
              // do your stuff here
      
              free(user_int.val); // free the memory at the end;
              return 0;
      }
      

      【讨论】:

      • 如果malloc返回NULL,这个程序会崩溃... ;)
      • 添加#include &lt;limits.h&gt;并将8替换为CHAR_BIT。
      • 将num_bit/CHAR_BIT 更改为(num_bit+CHAR_BIT-1)/CHAR_BIT 以支持非CHAR_BIT 多个位数(例如,13)。
      • 您现在可以删除since 8 bit =1 byte 评论。
      • 但是在调用 malloc 时将 int *val 更改为 char *val 并删除 sizeof(int)。
      猜你喜欢
      • 2015-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-17
      • 1970-01-01
      • 2014-05-06
      相关资源
      最近更新 更多