【问题标题】:c struct pointer issuesc结构指针问题
【发布时间】:2010-03-23 14:36:09
【问题描述】:

我正在尝试将一个结构转换为另一个结构,但我在转换和 some_func 下的 ma​​lloc 中遇到了不兼容的指针问题(结构布局相同)

struct stu1 **some_func(struct stu1 *my_struct)
{
   my_struct = (struct stu1 **)malloc(sizeof(struct stu1 *)*total_size);

   for(i=0;i<20;i++){
      my_struct[i] = (struct stu1 *)malloc(sizeof(struct stu1));
      printf("%s",my_struct[i++]->a);
   }
   return my_struct;
}

int main() 
{
   struct stu1 **my_struct;
   struct stu2 **my_struct2;
   struct stu3 **my_struct3;

   my_struct = some_func(my_struct);
   my_struct2 = (struct stu2**)some_func((struct stu1*)my_struct2);
   my_struct3 = (struct stu3**)some_func((struct stu1*)my_struct3);    
}

【问题讨论】:

  • 您缺少some_func 中的return 语句,并且您可能在参数和return 语句中提供了错误的* 数。愿意告诉我们代码的意图是什么?
  • 本意是不同的结构(相同的布局)需要通过some_func()以相同的方式填写
  • 这里有一个真正的问题,因为您显然正在尝试做一些复杂的事情,例如分配指向结构的指针数组或其他东西,但是因为您已经中性了所有变量名并且没有说出代码试图完成的任何事情,任何人都很难提供帮助。
  • 如果不同的结构都具有相同的布局,并且都以相同的方式初始化,为什么不只使用一种类型的结构呢?至少,让一个结构体作为另外两个结构体的唯一成员。

标签: c struct malloc


【解决方案1】:

几个问题。

首先,您到处都有不兼容的类型。在行中

my_struct = some_func(my_struct);

my_struct 的类型为struct stu1 **,但some_func 的定义需要struct stu1 * 类型的参数;这两种类型不一样。指向 T 的指针与指向 T 的指针的类型不同。

其次,你的选角体操不会如你所愿。指针类型不会自动兼容;它们的基类型必须兼容,不同的结构类型不兼容,即使它们的布局相同,例如:

struct {int x, int y} foo;
struct {int x, int y} bar;
struct S {int x, int y} blurga;
struct S bletch;

foobarbletch 是不同的类型并且不兼容,即使它们的布局相同。 blurgabletch 属于同一类型(结构 S)。如果struct stu2struct stu3 的大小与struct stu1 不同,那么您将无法为my_struct2my_struct3 分配正确的内存量。

为了清楚起见和您的理智,您应该为每种类型设置不同的分配函数,而不是试图将方形钉子强行插入五边形孔:

struct stu1 **stu1_alloc(size_t count)
{
  struct stu1 **arr = malloc(sizeof *arr * count);
  if (arr)
  {
    size_t i;
    for (i = 0; i < count; i++)
    {
      arr[i] = malloc(sizeof *arr[i]);
      if (arr[i])
      {
        // initialize arr[i] as necessary
      }
    }
  }
  return arr;
}

struct stu2 **stu2_alloc(size_t count)
{
  struct stu2 **arr = malloc(sizeof *arr * count);
  if (arr)
  {
    size_t i;
    for (i = 0; i < count; i++)
    {
      arr[i] = malloc(sizeof *arr[i]);
      if (arr[i])
      {
        // initialize arr[i] as necessary
      }
    }
  }
  return arr;
}

struct stu3 **stu3_alloc(size_t count)
{
  struct stu3 **arr = malloc(sizeof *arr * count);
  if (arr)
  {
    size_t i;
    for (i = 0; i < count; i++)
    {
      arr[i] = malloc(sizeof *arr[i]);
      if (arr[i])
      {
        // initialize arr[i] as necessary
      }
    }
  }
  return arr;
}

int main(void)
{
  struct stu1 **my_struct = stu1_alloc(SIZE);
  struct stu2 **my_struct2 = stu2_alloc(SIZE2);
  struct stu3 **my_struct3 = stu3_alloc(SIZE3);
  ...
}

是的,三个分配函数之间唯一不同的是类型。但是,如果不同的结构类型有不同的大小或不同的初始化需求,那么这是必要的。

请注意几件事。首先,我没有投射malloc() 的结果。有两个原因。其一,从 C89 及更高版本开始,您不必:malloc() 返回 void * 类型,该类型隐式转换为目标指针类型。两个,更重要的是,如果我忘记包含 stdlib.h 或者在范围内没有 malloc() 的原型,那么放弃该类型将触发“不兼容类型”警告(因为假定未声明的函数返回 @ 987654342@,并且不能将 int 值隐式转换为指针类型)。如果你转换malloc()的返回值,那么你在运行时抑制了警告和风险问题(因为malloc()返回的值将从void *转换为int,然后从int转换为目标指针类型,不保证工作)。

其次,我在对象上使用sizeof,而不是类型。这有两个好处。一,代码更容易阅读。二、如果我改变了对象的类型,我就不必每次调用都回过头来改变malloc()

如果你真的不想拥有三个独立的分配函数,你可以试试这样的宏魔法:

#define ALLOC_STU(target, size)                \
  do {                                         \
    target = malloc(sizeof *target * size);    \
    if (target)                                \
    {                                          \
      size_t i;                                \
      for (i = 0; i < size; i++)               \
      {                                        \
        target[i] = malloc(sizeof *target[i]); \
      }                                        \
    }                                          \
  } while(0)

int main(void)
{
  struct stu1 **my_struct;
  ...
  ALLOC_STU(my_struct, SIZE);
  ...
}

虽然我认为单独的分配函数是更安全的方法。

【讨论】:

    【解决方案2】:
    struct stu1 **some_func(struct stu1 *my_struct)
    {
       my_struct = (struct stu1 **)malloc(sizeof(struct stu1 *)*total_size);
    

    my_struct 的类型为 struct stu1 *,但您正在尝试分配(已转换)struct stu1 **

    【讨论】:

      【解决方案3】:

      只是猜测,你想要这样的东西吗:

      
      struct stu1 **some_func(struct stu1 ***my_struct) 
      { 
         *my_struct = (struct stu1 **)malloc(sizeof(struct stu1 *)*total_size); 
      
         for(i=0;i<20;i++){ 
            (*my_struct)[i] = (struct stu1 *)malloc(sizeof(struct stu1)); 
            printf("%s",(*my_struct)[i++]->a); 
         } 
         return *my_struct; 
      } 
      
      int main()  
      { 
         struct stu1 **my_struct; 
         struct stu2 **my_struct2; 
         struct stu3 **my_struct3; 
      
         my_struct = some_func(&my_struct); 
      } 
      

      但这没有多大意义。返回值不是必需的。

      【讨论】:

        【解决方案4】:

        从哪里开始...

        1. 您必须匹配您的类型。 some_func() 需要一个指针;在一种情况下,您传递的是双指针(指向指针的指针)。
        2. 在 some_func() 中,第一个 malloc() 存在类型不匹配。它正在尝试将双指针设置为单指针。
        3. 在 some_func() 中,第二个 malloc() 有另一个类型不匹配。它正在尝试将非指针(结构)设置为指针。

        在 some_func() 中,您似乎正在尝试动态地处理二维数组。作为参考,有两种使用 malloc() 的方法。

        方法#1。 (没有错误检查)

        struct stu1 **some_func(int dim1, int dim2)
        {
           struct stu1 **my_struct;
           int  i;
        
           /* Allocate space for an array of <dim1> pointers */
           my_struct = (struct stu1 **) malloc(sizeof(struct stu1 *) * dim1);
        
           /* Allocate <dim2> elements for each pointer */
           for (i = 0; i < dim1; i++){
              my_struct[i] = (struct stu1 *) malloc (sizeof (struct stu1) * dim2);
           }
           return (my_struct);
        }
        

        方法#2。 (同样,没有错误检查)

        struct stu1 **some_func(int dim1, int dim2)
        {
           struct stu1 **my_struct;
           int  i;
           char *data;
        
           /* Allocate space for everything. */
           data = (char *) malloc((sizeof (struct stu1 *) * dim1) + (dim1 * dim2 * sizeof (struct stu1)));
           my_struct = (struct stu1 **) data;
        
           /* Initialize pointers to pointers. */
           data = (char *) &my_struct[dim1];
           for (i = 0; i < dim1; i++) {
              my_struct[i] = (struct stu1 *) data;
              data += sizeof (struct stu1) * dim2;
           }
           return (my_struct);
        }
        

        每种方法都有其优点和缺点。希望这会有所帮助。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-03-10
          • 2013-09-12
          相关资源
          最近更新 更多