【问题标题】:C Malloc of array within a struct结构内数组的 C Malloc
【发布时间】:2018-03-27 15:17:52
【问题描述】:

我正在尝试使用 main 中的值 malloc 结构。我已经搜索了这样做的方法,但找不到答案。我有 3 种类型的硬币,我想将它们的价格放入 ret。如何从结构中声明 ret

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

typedef struct
{

    double *ret;

}coin;


void ini(int a)
{
    ret = (double*)malloc(a*sizeof(double));
}


int main(void){

    long int a=250;
    int n_coins=3;


        coin *m = (coin*)malloc(n_coins*sizeof(coin));

        ini(a);

        m[0].ret[0] = 2000;
        printf("%lf", m[0].ret[0]);



    return 0;
}

【问题讨论】:

  • return 是 C 中的保留关键字,因此您不能使用它。对于初学者,为什么不尝试malloc main 中的数组?
  • 你不能在C语言中使用return作为变量名。
  • 函数中的变量retini() 在程序的其他任何地方都不可见。建议取消该功能。

标签: c arrays struct malloc void


【解决方案1】:

如果我有你的代码并且必须改进它,我会选择

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

// The kernel style guide https://www.kernel.org/doc/html/v4.10/process/coding-style.html discourages typedefs for structs
typedef struct moeda {
    double *return_value;
} moeda;


// return a struct here:
moeda initialize_return(int a)
{
    moeda ret;
    ret.return_value = malloc(a*sizeof(double));
    return ret;
}


int main(void) {
    long int a=250;

    moeda m = initialize_return(a);

    m.return_value[0] = 2000;
    printf("%lf", m.return_value[0]);

    return 0;
}

(最好所有标识符都用英文)。

这将是第一步。然后我可能会意识到这个结构并不是真的需要并替换它:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

double * initialize_double_array(int a)
{
    return malloc(a*sizeof(double));
}

int main(void) {
    long int a=250;

    double * arr = initialize_double_array(a);

    arr[0] = 2000;
    printf("%lf", arr[0]);

    return 0;
}

OTOH,如果上述结构中还有其他字段,我可能会决定它们是否应该与这个数组一起初始化。

一些变种:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

// The kernel style guide https://www.kernel.org/doc/html/v4.10/process/coding-style.html discourages typedefs for structs
struct moeda {
    int num_values;
    double *values;
};

// only fill a struct here:
// i. e. take a pre-initialized struct and work with it:
void moeda_alloc_values(struct moeda * data) 
{
    data->return_value = malloc(data->num_values * sizeof(double));
}

// return a struct here:
struct moeda initialize_moeda(int num) 
{
    struct moeda ret;
    ret.num_values = num;
    ret.return_value = malloc(num * sizeof(double));
    // or just moeda_alloc_values(&ret);
    return ret;
}

int main(void) {
    long int a=250;

    struct moeda m = initialize_return(a);
    m.return_value[0] = 2000;
    printf("%lf", m.return_value[0]);

    struct moeda m2;
    m2.num_values = 20;
    moeda_alloc_values(&m2);
    m2.return_value[0] = 2000;
    printf("%lf", m2.return_value[0]);

    return 0;
}

结构返回函数的优点是在返回后你有一个“容易填充”的结构。

另一个通过指针修改结构的函数的优点是它可以处理任何可能预填充、可能分配的结构,并且它可以处理单个字段,而不必考虑所有字段。

【讨论】:

  • 我有一个 250 行的代码,我总结了它来问我需要问什么。确实需要该结构。
  • @Ana 好的,那么 - 是 struct static resp 中的其他字段。它们是否也必须被上述功能覆盖?
【解决方案2】:

首先return是C语言中保留的keyword,不能使用保留关键字作为变量名。

其次,如果你想在其他函数中为任何数据类型的数组分配内存,那么在函数中声明一个变量,调用malloc,通过malloc分配所需的空间,并返回分配空间的第一个元素的地址.如果你不返回地址分配的空间将不知道被调用的函数(这里main())并且它无法访问分配的内存空间。你可以这样做:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

typedef struct
{
   double *var;
}moeda;


double *ini(int n)
{
   double *arr;
   arr = malloc(n*sizeof(*arr));
   return arr;
}

int main(void){

   long int a=250;

    moeda m;

    m.var=ini(a);

    m.var[0] = 2000;
    printf("%lf", m.var[0]);



    return 0;
}

【讨论】:

    【解决方案3】:

    返回是 c 中的关键字。您不能将其用作变量名。 我也不清楚这个问题。 什么是“moeda m”;莫达在这里?如果这不是英文 C,我很抱歉。

    【讨论】:

    • Moeda只是我用来测试的名字,没有任何意义
    • 知道了,krpra 的答案非常接近,唯一的问题是以下行 m.var=inicializaretorno(a); inicializaretorno 返回指向 moeda 的指针,但 m.var 会收集双精度指针,因此不建议这样做。
    【解决方案4】:

    我假设您只是想从 main 中调用的函数为结构分配内存。为了清楚起见,我更改了您的变量名称。 因此,首先正如其他人所说,您不能使用 return 作为变量名。我还建议使用结构的大小而不仅仅是双精度,因为将来您可能会在结构中拥有多个变量。

    如果你想使用 main 中的函数,你必须传递一个指向函数的指针,然后使用 malloc 为其分配内存,然后返回它。或者您可以将结构指针设为全局作为另一种选择。

    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <string.h>
    #include "stdafx.h"
    #include <malloc.h>
    
    typedef struct
    {
        double number;
    }example;
    
    example *allocateMemory(int a, example *s)
    {
        s = (example*)malloc(a * sizeof(example));
        return s;
    }
    
    int main() {
    
        long int a = 250;
        example *structure = NULL;
        structure = allocateMemory(a, structure);
    
        structure[0].number = 2000;
    
        printf("%lf\n", structure[0].number);
    
        //cleaning up memory
        free(structure);
        structure = NULL;
        return 0;
    }
    

    只是其他一些注释,我让我的示例结构等于 null,因为编译器抱怨未初始化的局部变量。

    在你的代码中,你有这个。

    m.retorno[0] = 2000;
    

    但我假设您想访问结构数组中的第一个数字,所以应该是:

    structure[0].number = 2000;
    

    【讨论】:

      【解决方案5】:

      对于这个具体的例子,我会做如下的事情:

      #include <stdio.h>
      #include <stdlib.h>
      #include <math.h>
      #include <string.h>
      
      typedef struct
      {
         size_t  nLen;    // number of elements allocated for var
         double *var;     // pointer to a list of double variables
      } moeda;
      
      // struct is small so just initialize the whole thing and return it
      // from the initialization routine.
      moeda iniMoeda (size_t n)
      {
         moeda x = {0};
      
         x.var = malloc(n * sizeof(double));   // try to allocate the requested number of doubles
         if (x.var) x.nLen = n;     // if allocated then remember number of doubles
      
         return x;
      }
      
      // free a moeda variable. we require a pointer so that we can reset
      // the moeda variable to a known state of NULL pointer and zero allocation
      // length so that we can easily catch using the variable after the memory
      // has been freed. Hope for Address exception on a NULL pointer if this
      // variable is used after freeing.
      void freeMoeda (moeda *x)
      {
          // free the allocated doubles and clear everything.
          // if x->var is NULL then free() does nothing.
          free (x->var); x->var = NULL; x->nLen = 0;
      }
      
      int main(void)
      {
          size_t  a = 250;
          moeda   m = iniMoeda (a);
      
          if (m.var) {
              // allocation worked so lets test our space
              m.var[0] = 2000;
              printf("%lf", m.var[0]);
          } else {
              printf ("m.var is NULL.\n");
          }
      
          freeMoeda (&m);
          return 0;
      }
      

      【讨论】:

        【解决方案6】:

        以下建议的代码:

        1. 干净编译
        2. 记录包含每个头文件的原因
        3. 执行所需的操作
        4. 自行清理
        5. 包含关于代码中每个步骤的嵌入式 cmets

        注意:代码必须一致、可读并执行所需的功能

        现在,建议的代码:

        // for ease of readability and understanding:
        // 1) insert a space:
        //    after commas,
        //    after semicolons,
        //    inside brackets,
        //    inside parens,
        //    around C operators
        // 2) separate code blocks
        //    ( 'for' 'if' 'else' 'while' 'do...while' 'switch' 'case' 'default' )
        //    via a single blank line
        // 3) variable (and parameter) names should indicate
        //    'content' or 'usage' (or better, both)
        
        #include <stdio.h>   // printf(), perror()
        #include <stdlib.h>  // malloc(), free(), exit(), EXIT_FAILURE
        // do not include header files those contents are not used
        //#include <math.h>
        //#include <string.h>
        
        // added 'sCOIN' tag name to make it easier to use debugger
        // since most debuggers use the tag name to reference fields inside a struct
        typedef struct  sCOIN
        {
            double *ret;
        } coin;
        
        
        int main( void )
        {
            // 'malloc()' expects its parameters to be of type 'size_t'
            size_t n_coins=3;
            coin  mycoin;
        
            // do not cast the returned value from 'malloc()', 'calloc()', 'realloc()'
            // as the returned type is 'void*' which can be assigned to any pointer
            //coin *m = (coin*)malloc(n_coins*sizeof(coin));
            mycoin.ret = malloc( n_coins * sizeof( double ) );
            // always check to assure the operation was successful
            if( !mycoin.ret )
            {
                // 'perror()' outputs the enclosed text
                // and the text of why the system thinks the error occurred
                // to 'stderr'
                perror( "malloc failed" );
                exit( EXIT_FAILURE );
            }
        
            // implied else, malloc successful
        
            // the field in 'coin' is declared a DOUBLE so assign a double
            // not a integer.  I.E include a decimal point '.'
            mycoin.ret[ 0 ] = 2000.0;
            printf( "%lf", mycoin.ret[ 0 ] );
        
            // code should always clean up after itself
            // I.E. don't leave a mess nor depend on the OS to cleanup.
            free( mycoin.ret );
            return 0;
        }
        

        【讨论】:

          猜你喜欢
          • 2015-07-30
          • 2022-01-07
          • 2012-09-19
          • 2021-05-29
          • 1970-01-01
          • 2018-12-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多