C - 初始化struct member - 指针数组。第二个元素的值不正确

时间:2018-03-05 21:20:41

标签: c arrays pointers memory-address

我有带参数的结构。我想初始化它们中的每一个并将它们的地址放入paramList数组和paramListSize字段中的初始化参数数量。 我希望在没有尽可能少的步骤的情况下预先指定参数数量的情况下实现这一目标。

我写的解决方案我有点满意,但它并没有真正起作用:-)第二个元素被随机数覆盖,我不明白为什么。

你能帮忙吗?

我正在使用C ++编译器,但是用C语言编写。

这是代码和沙箱reference doc

if "%startnum%"=="0" goto fail

2 个答案:

答案 0 :(得分:2)

您没有为paramlist分配内存;相反,你指定一个指向局部变量的指针,一旦它的生命周期在函数结束时变为无效。因此,访问它是不确定的行为。

以下代码显示了如何克服此问题;

int initConfig(configuration *config)
{
  config->paramListSize = 0;
  config->paramList = calloc(3, sizeof(parameter));
  config->paramList[0] = &config->param1;
  config->paramList[1] = &config->param2;
  config->paramList[2] = &config->param3;

  initParameter(&config->param1, 100, &config->paramListSize);
  initParameter(&config->param2, 200, &config->paramListSize);
  initParameter(&config->param3, 300, &config->paramListSize);
}

答案 1 :(得分:2)

您的方法存在的问题是test是一个已分配的局部变量,堆栈将在int initConfig(configuration *config)返回后消失。

所以这次尝试

config->paramList = test;

必须替换为内存的分配,这将在函数返回后继续存在。

  config->paramList = (parameter**)calloc(config->paramListSize, sizeof(parameter));

现在,您可以将temp中收集的指针复制到paramList

  for (int i = 0; i< config->paramListSize; i++)
  {
    config->paramList[i] = test[i];
  }

我们还检查内存分配是否成功,并相应地从0返回-int initConfig 1。

main结束时释放内存。

该计划遵循您的想法:

#include "stdio.h"
#include "stdlib.h"
#include "string.h"

struct parameter
{
  int field;
};

struct configuration {
  parameter** paramList;
  int paramListSize;
  parameter param1;
  parameter param2;
  parameter param3;
};

parameter *initParameter(parameter *param, int value, int *paramListSize)
{
   param->field = value;

  (*paramListSize)++;

  return param;
}

int initConfig(configuration *config)
{
  config->paramListSize = 0;

  // This array gathers the parameter pointers but it will be lost when `initConfig` returns:
  parameter* test[] =
  {
    initParameter(&config->param1, 100, &config->paramListSize),
    initParameter(&config->param2, 200, &config->paramListSize),
    initParameter(&config->param3, 300, &config->paramListSize)
  };

  // Allocate memory for the list of parameters:
  config->paramList = (parameter**)calloc(config->paramListSize, sizeof(parameter));

  if (config->paramList == NULL) // calloc failed
    return -1;

  // copy the pointers to the paramList
  for (int i = 0; i< config->paramListSize; i++)
  {
    config->paramList[i] = test[i];
  }

  return 0;
}

void printConfig(configuration *config)
{
  for (int i= 0; i < config->paramListSize; i++)
  {
    printf("param %d = %d\n", i + 1, config->paramList[i]->field);
  }
}

int main(void)
{
   configuration config;

   if( initConfig(&config) == 0){  // initConfig returned with success
      printConfig(&config);
      free(config.paramList);       // free the memory.
   }
   else {
      printf("calloc failed - initConfig failed!\n");
   } 
   return 0;
}

输出:

param 1 = 100
param 2 = 200
param 3 = 300