【问题标题】:Use malloc with structure使用具有结构的 malloc
【发布时间】:2014-04-07 09:33:58
【问题描述】:

我在结构中使用 malloc,但遇到一些错误,例如

错误 1 ​​错误 C2440: 'initializing' : cannot convert from 'void *' to 'my_vector *' c:\lab3\lab3\linalg.cpp 19 lab3

我正在制作 MPI 应用程序并设置所有需要的设置。 我尝试了一些解决方案,但没有帮助。

linalg.cpp

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

#include <mpi.h>

#include "linalg.h"

void fatal_error(const char *message, int errorcode)
{
  printf("fatal error: code %d, %s\n", errorcode, message);
  fflush(stdout);
  MPI_Abort(MPI_COMM_WORLD, errorcode);
}

struct my_vector *vector_alloc(int size, double initial)
{
  struct my_vector *result = malloc(sizeof(struct my_vector) +
                                    (size-1) * sizeof(double));
  result->size = size;

  for(int i = 0; i < size; i++)
  {
    result->data[i] = initial;
  }

  return result;
}

void vector_print(FILE *f, struct my_vector *vec)
{
  for(int i = 0; i < vec->size; i++)
  {
    fprintf(f, "%.15lf ", vec->data[i]);
  }
  fprintf(f, "\n");
}

struct my_matrix *matrix_alloc(int rows, int cols, double initial)
{
  struct my_matrix *result = malloc(sizeof(struct my_matrix) + 
                                    (rows * cols - 1) * sizeof(double));

  result->rows = rows;
  result->cols = cols;

  for(int i = 0; i < rows; i++)
  {
    for(int j = 0; j < cols; j++)
    {
      result->data[i * cols + j] = initial;
    }
  }

  return result;
}

void matrix_print(FILE *f, struct my_matrix *mat)
{
  for(int i = 0; i < mat->rows; i++)
  {
    for(int j = 0; j < mat->cols; j++)
    {
      fprintf(f, "%lf ", mat->data[i * mat->cols + j]);
    }
    fprintf(f, "\n");
  }
}

struct my_matrix *read_matrix(const char *filename)
{
  FILE *mat_file = fopen(filename, "r");
  if(mat_file == NULL)
  {
    fatal_error("can't open matrix file", 1);
  }

  int rows;
  int cols;
  fscanf(mat_file, "%d %d", &rows, &cols);

  struct my_matrix *result = matrix_alloc(rows, cols, 0.0);
  for(int i = 0; i < rows; i++)
  {
    for(int j = 0; j < cols; j++)
    {
      fscanf(mat_file, "%lf", &result->data[i * cols + j]);
    }
  }

  fclose(mat_file);
  return result;
}

struct my_vector *read_vector(const char *filename)
{
  FILE *vec_file = fopen(filename, "r");
  if(vec_file == NULL)
  {
    fatal_error("can't open vector file", 1);
  }

  int size;
  fscanf(vec_file, "%d", &size);

  struct my_vector *result = vector_alloc(size, 0.0);
  for(int i = 0; i < size; i++)
  {
    fscanf(vec_file, "%lf", &result->data[i]);
  }

  fclose(vec_file);
  return result;
}

void write_vector(const char *filename, struct my_vector *vec)
{
  FILE *vec_file = fopen(filename, "w");
  if(vec_file == NULL)
  {
    fatal_error("can't open vector file", 1);
  }

  vector_print(vec_file, vec);

  fclose(vec_file);
}

我在这个地方有问题

struct my_vector *result = malloc(sizeof(struct my_vector) +
                                    (size-1) * sizeof(double));

【问题讨论】:

  • 您是否使用 C++ 编译器编译 C 代码?
  • @lethal-guitar 他可能是这样。许多 C/C++(统一)编译器根据扩展决定使用哪种语言。所以代码编译为C++
  • 这看起来很像 Visual Studio 错误代码。该编译器确实是一个 C++ 编译器,即使我将其设置为编译为 C 代码并且文件具有 .c 扩展名,我似乎仍然会收到该错误。
  • 我尝试过像 C 和 C++ 一样,但是当我选择 C ​​编译器时,我认为我有很多与 c99 相关的错误。
  • 是的,Visual Studio(至少在我使用的版本:2010 之前)不支持 C99。

标签: c++ c struct malloc mpi


【解决方案1】:

您的代码可能正在使用 C++ 编译器进行编译。您的代码名为“.cpp”这一事实也很能说明问题,这是 C++ 的典型扩展。

在 C++ 中,您不能在没有强制转换的情况下将 void * 转换为其他指针:

my_vector *result = (my_vector *) malloc(...);

但您可以删除struct,因为它隐含在 C++ 中。此外,在 C++ 中,您应该使用 new:

my_vector *result = new my_vector[...];

这消除了投射的需要。

如您所见,C 和 C++ 并不相同。如果你想用 C 语言编程,你需要一个 C 编译器。

【讨论】:

    【解决方案2】:

    malloc 返回void *。在 C++ 中,您必须将其转换为适当的指针类型:

    struct my_vector *result = (struct my_vector *)malloc(...)
    

    【讨论】:

    • 没关系!但是我可以像 C 一样编译但支持这段代码吗?我想我只需要支持 c99 标准。我正在使用 VS 2008。
    • @АндрейСердюк 不适用于 VS2008。直到最近,微软几乎都忽略了 C99。 VS2013 增加了一些支持,但在早期版本中,您只能使用 C89。
    【解决方案3】:
    struct my_matrix *result = malloc(sizeof(struct my_matrix) + 
                                    (rows * cols - 1) * sizeof(double));
    

    在 C++ 中,没有从 void * 到其他指针类型的隐式转换,因此您必须强制转换 malloc 返回的值。请注意,您可能应该改用new[]

    这行代码表明您打算在struct my_matrix 内的数组范围之外进行写入。这将导致未定义的行为。可以将 MPI 结构设计为不使用这种所谓的“struct hack”。对于一些可以用来为设计建模的示例,请查看开源 MPI 库的标头。

    注意。我看到您将这篇文章标记为“C”和“C++”。请确定您使用的语言。试图编写在两种不同语言之间源代码兼容的代码是一个糟糕的主意。标头,是的,函数实现,不是。

    【讨论】:

      【解决方案4】:

      代码看起来像一个合法的 C,所以它会用 C 编译器编译。但是,它不会在 C++ 中。 C++ 有更强的类型检查规则。但是,将 malloc 的结果(即void*)转换为适当的指针类型应该可以工作。

      【讨论】:

        【解决方案5】:

        您正在将 C 代码编译为 C++ 代码。在 C++ 中,您需要针对您的特定情况进行强制转换(请参阅其他答案以获取示例),而在 C 中则不需要。

        重命名您的文件,使其具有*.c 扩展名,并且应该可以正常工作。

        【讨论】:

          猜你喜欢
          • 2013-05-30
          • 2011-06-26
          • 2011-12-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-02-26
          • 1970-01-01
          相关资源
          最近更新 更多