C - 初始化结构成员 - 指针数组。第二个元素的值不正确

C - Initializing struct member - array of pointers. Second element has incorrect value

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

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

你能帮忙吗?

我正在使用 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);
}

您没有为 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);
}

你的方法的问题是 test 是分配的局部变量和堆栈,它将消失一次 int initConfig(configuration *config) returns.

所以这次尝试

config->paramList = test;

必须替换为在函数 return.

后仍然存在的内存分配
  config->paramList = (parameter**)calloc(config->paramListSize, sizeof(parameter));

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

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

我们还检查内存分配是否成功,并相应地检查 return 0int 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