【问题标题】:Cannot assign values to struct members无法为结构成员赋值
【发布时间】:2016-11-05 00:19:49
【问题描述】:

我已经动态分配了一个代表一系列点的结构数组。但是,当我尝试为其成员分配值时,程序分配的值与预期的不同。我做错了什么?

程序的输出:

xy[0].x= 0 
xy[0].y= 0 
xy[1].x= 1 
xy[1].y= 1 
xy[2].x= 2 
xy[2].y= 2 
xy[3].x= 1041 
xy[3].y= 0 

代码:

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

int n;

struct point{
  int x,y;
};
typedef struct point Point; 


void resize(Point*xy) 
{
    xy=(Point*)realloc(xy,sizeof(Point));

    for (n=0;n<4;n++)
    {
    xy[n].x=n;
    xy[n].y=n;
    }   
}


int main () 
{
   Point *xy;
   xy=(Point*)malloc(2*sizeof(Point));

   for (n=0;n<2;n++){
       xy[n].x=n;
       xy[n].y=n;
   }       

   resize(xy) ; 
   for (n = 0; n<4; n++) {
       printf("xy[%i].x= %i \n",n,xy[n].x);
       printf("xy[%i].y= %i \n",n,xy[n].y);
   }       

   free(xy);
   return 0;
}

【问题讨论】:

  • resize()中,你只有realloc()有足够的空间容纳一个结构......并将结果从参数列表中保存到xy,所以如果地址更改@中的xy 987654327@ 仍将包含旧地址(尽管由于您正在缩小数组,realloc() 可能会返回相同的地址)。
  • 您应该将Point ** 而不是Point * 传递给resize(),或者返回Point * 以分配回main() 中的xy
  • 始终检查可能产生严重错误的函数的结果,例如realloc。并且不要将 malloc 和朋友的结果投射到 C 中!

标签: c arrays dynamic struct structure


【解决方案1】:

我做错了什么?

  • 问题是,当您重新分配xy int resize() 函数的大小时,您没有分配足够的内存:

    void resize(Point*xy) {
    xy = (Point*) realloc( xy, sizeof(Point));
    
  • 这里,realloc(xy,sizeof(Point)); 仅为1 结构分配内存,因此您只能访问xy[0].xxy[0].y

  • 但是,在 for 循环中,您可以访问 xy[1]xy[2]xy[3] ... 这是

    访问越界,这会导致undefined behavior

因此,您会得到未定义的输出。


解决方案:

使用realloc()分配足够的内存

  • 当您迭代 for 循环 4 ( n= 0 到 3 ) 次时,我想您需要为 4 结构分配内存

  • 只需将 4 乘以 realloc() 函数中 resize() 的第二个参数

    xy = (Point*)realloc( xy, 4*sizeof(Point)); //multiply with 4
    
  • 这里分配了足够的内存来存储4结构


输出: (更改后)

xy[0].x= 0 
xy[0].y= 0 
xy[1].x= 1 
xy[1].y= 1 
xy[2].x= 2 
xy[2].y= 2 
xy[3].x= 3 
xy[3].y= 3  
  • 你得到的结果和预期的一样:)

建议:

首先,

  • 不要 投射malloc()的值(和realloc()因为它们返回 void 类型,该类型会自动转换为分配给它的指针的数据类型。

  • 所以而不是:

    xy = (Point*)realloc(xy,4*sizeof(Point)); //same for malloc dont cast
    
  • 使用

    xy= realloc(xy,4*sizeof(Point));
    

更多阅读请看:click


然后,

  • 不要使用int main(),而是使用int main(void),因为没有参数被发送到main()函数。但是,在第一种情况是int main(),可以发送任意数量的参数进入main()函数...

【讨论】:

  • 索引括号对他取消引用 -- xy[0].x 会起作用,xy[0]-&gt;x 不会。
  • @Dmitri 谢谢你知道了......谢谢你的提及:) 我已经编辑了答案
  • @PaulStelian true.. 但由于 OP 没有向 main() 发送任何参数,我认为建议他使用 int main(void) 会更好
  • @PaulStelian 在 C++ 中,没有区别,都是一样的。这两个定义在 C 中也有效,但是第二个带有 void 的定义在技术上被认为更好,因为它清楚地指定 main 只能在没有任何参数的情况下调用。有关更多信息,请参阅:geeksforgeeks.org/difference-int-main-int-mainvoid
  • @PaulStelian 没问题 :) 顺便说一句,不需要在 main() 结束时返回 0 ..因为大多数现代编译器在到达 main 结束时会自动返回零。显然这个信息是由其他用户分享给我的,所以我只是传递知识:)
【解决方案2】:

你的 resize 函数有两个问题:

void resize(Point*xy) {
    xy=(Point*)realloc(xy,sizeof(Point));  // changes local variable

    for (n=0;n<4;n++)
    {
        xy[n].x=n;
        xy[n].y=n;
    }   
}

首先,您将分配的大小从2*sizeof(Point) 缩小到sizeof(Point)reallocs 第二个参数是分配的新 total 大小,而不是您要添加的大小。

其次,你的函数只修改了局部变量xy,它不会返回它或让调用者知道。主要:

   // imagine xy = 0x10000.
   resize(xy) ;  // frees 0x10000 and allocates new memory
   // xy here is still 0x10000

您需要在调整大小时采用Point** 指针,或者您需要调整大小以返回它的本地 xy 值:

Point* resize(Point*xy) {
    int n;
    xy=(Point*)realloc(xy, 4*sizeof(Point));

    for (n=0;n<4;n++)
    {
        xy[n].x=n;
        xy[n].y=n;
    }   

    return xy;
}

void resize(Point** xyp) {
    int n;
    *xyp=(Point*)realloc(*xyp, 4*sizeof(Point));

    for (n=0;n<4;n++)
    {
        (*xyp)[n].x=n;
        (*xyp)[n].y=n;
    }   
}

例子:

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

typedef struct {
    int x, y;
} Point;

void resize(Point** xyp) {
    int n;
    *xyp=(Point*)realloc(*xyp, 4*sizeof(Point));

    for (n=0;n<4;n++)
    {
        (*xyp)[n].x=n;
        (*xyp)[n].y=n;
    }   
}

int main () {
    int n;
    Point *xy;
    xy=(Point*)malloc(2*sizeof(Point));

    for (n=0;n<2;n++)
    {
        xy[n].x=n;
        xy[n].y=n;
    }       

   resize(&xy) ; 

   for (n = 0; n<4; n++) {
        printf("xy[%i].x= %i \n",n,xy[n].x);
        printf("xy[%i].y= %i \n",n,xy[n].y);
   }       

   free(xy);

   return 0;
}

http://ideone.com/gIntgl

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-19
    • 2015-12-20
    • 1970-01-01
    • 2013-10-07
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    相关资源
    最近更新 更多