简体   繁体   English

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

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

I've got struct with parameters. 我有带参数的结构。 I want to initialize every single of them and put their addresses into paramList array and number of initialized params in paramListSize field. 我想初始化它们中的每一个,并将它们的地址放入paramList数组中,并将其初始化为paramListSize字段中的数目。 I want to achieve this without specifying number of params upfront and with as little steps as possible. 我想在不预先指定参数数量且步骤尽可能少的情况下实现此目的。

I wrote solution that I'm somewhat happy with, but it is not really working :-) Second element is being overwritten by random number and I have no idea why. 我写了一些令我满意的解决方案,但是它实际上并没有起作用:-)第二个元素被随机数覆盖,我不知道为什么。

Can you help? 你能帮我吗?

I'm using C++ compiler, but writing in C. 我正在使用C ++编译器,但是用C编写。

Here's code and sandbox https://repl.it/repls/SourRoughDrawing 这是代码和沙箱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);
}

You are not allocating memory for paramlist ; 你是不是分配内存paramlist ; instead, you assign a pointer to a local variable which becomes invalid once its lifetime ends at the end of the function. 相反,您将指针分配给局部变量,该局部变量的生存期在函数末尾时将变为无效。 Accessing it is undefined behaviour then. 然后,访问它是未定义的行为。

The following code shows how to overcome this issue; 以下代码显示了如何解决此问题;

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);
}

The problem with your approach is that test is a local variable allocated and the stack and it will be gone once int initConfig(configuration *config) returns. 您的方法存在的问题是, test是分配给局部变量和堆栈的,一旦int initConfig(configuration *config)返回,它将消失。

So this attempt 所以这个尝试

config->paramList = test;

has to be replaced with allocation of the memory which will survive the function return. 必须替换为可以在函数返回后保留的内存分配。

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

Now you you can copy the pointers gathered in temp to paramList 现在您可以将以temp方式收集的指针复制到paramList

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

We also check if memory allocation was successful and return 0 or - 1 from the int initConfig accordingly. 我们也检查,如果内存分配成功,返回0-从1 int initConfig相应。

At the end of main memory is freed. main内存末尾被释放。

The program follows your ideas: 该程序遵循您的想法:

#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;
}

Output: 输出:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM