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

问题描述 投票:0回答:2

我有结构参数。我想初始化它们中的每一个并将它们的地址放入paramList数组和paramListSize字段中的初始化参数数量。我想要实现这一点,而不是预先指定params的数量,并尽可能少地执行步骤。

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

你能帮我吗?

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

这是代码和沙箱https://repl.it/repls/SourRoughDrawing

#include "stdio.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;
  parameter* test[] =
  {
    initParameter(&config->param1, 100, &config->paramListSize),
    initParameter(&config->param2, 200, &config->paramListSize),
    initParameter(&config->param3, 300, &config->paramListSize)
  };
  config->paramList = test;

  // dirty failed attemp to fix :-)
  for (int parameterIndex = 0; parameterIndex < config->paramListSize; parameterIndex++)
  {
    config->paramList[parameterIndex] = test[parameterIndex];
  }
}

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

int main(void)
{
  configuration config;
  initConfig(&config);
  printConfig(&config);
}
c arrays pointers memory-address
2个回答
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 initConfig1。

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

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);
}
© www.soinside.com 2019 - 2024. All rights reserved.