更新结构中的变量值会导致同一结构中的另一个变量被修改

时间:2019-05-07 09:08:27

标签: c struct malloc flexible-array-member

我正在编写一个处理交叉路口的交通量并返回给定时间交叉路口的交通量的代码。

基本上我遇到的问题是一个结构数组,其中每个结构包含2个向量:一个具有交叉点的坐标(x,y),另一个跟踪在时间t进入那个交叉点的车数(每个插槽)从0到n代表时间,其中的值是当时穿越的汽车数量。

这是结构:

typedef struct intersection {
  int coords[2];
  int timeslots[];
} intersection;

包含在此结构的交集数组中:

typedef struct simulation {
  int h_streets; //row (horizontal streets)
  int v_streets; //column (vertical streets)
  int n_cars;    //cars number
  int n_trips;   //trips number

  car car_pos [1000];

  intersection intersections [];
} simulation;

然后使用malloc分配内存,以在读取所需数据时定义灵活数组的实际数组大小:

  struct simulation * this = malloc( sizeof(simulation) + (sizeof(intersection)*(h_streets*v_streets)*(sizeof(int)*(max_time+1001))) );

如前所述,当读取有关汽车从一个位置到另一个位置的行程的数据时,我要做的是,当汽车在那个时间穿过交叉点时,将时隙[t]递增一个。

问题在于,当我使用while周期中包含的这一行代码时,

this->intersections[curr_int].timeslots[starting_t+travel_t]++;

coords数组中的值被修改。

下面是在每个周期仅打印出交点坐标的示例:

------------------
i: 0, h: 0, v: 0
i: 1, h: 0, v: 1
i: 2, h: 0, v: 2
i: 3, h: 0, v: 3
i: 4, h: 1, v: 0
i: 5, h: 1, v: 1
i: 6, h: 1, v: 2
i: 7, h: 1, v: 3
i: 8, h: 2, v: 0
i: 9, h: 2, v: 1
i: 10, h: 2, v: 2
i: 11, h: 2, v: 3
i: 12, h: 3, v: 0
i: 13, h: 3, v: 1
i: 14, h: 3, v: 2
i: 15, h: 3, v: 3
------------------
------------------
i: 0, h: 0, v: 0
i: 1, h: 1, v: 1
i: 2, h: 0, v: 2
i: 3, h: 0, v: 3
i: 4, h: 1, v: 0
i: 5, h: 1, v: 1
i: 6, h: 1, v: 2
i: 7, h: 1, v: 3
i: 8, h: 2, v: 0
i: 9, h: 2, v: 1
i: 10, h: 2, v: 2
i: 11, h: 2, v: 3
i: 12, h: 3, v: 0
i: 13, h: 3, v: 1
i: 14, h: 3, v: 2
i: 15, h: 3, v: 3
------------------
------------------
i: 0, h: 0, v: 0
i: 1, h: 1, v: 2
i: 2, h: 0, v: 2
i: 3, h: 0, v: 3
i: 4, h: 1, v: 0
i: 5, h: 1, v: 1
i: 6, h: 1, v: 2
i: 7, h: 1, v: 3
i: 8, h: 2, v: 0
i: 9, h: 2, v: 1
i: 10, h: 2, v: 2
i: 11, h: 2, v: 3
i: 12, h: 3, v: 0
i: 13, h: 3, v: 1
i: 14, h: 3, v: 2
i: 15, h: 3, v: 3
------------------
------------------
i: 0, h: 0, v: 0
i: 1, h: 1, v: 2
i: 2, h: 0, v: 2
i: 3, h: 0, v: 3
i: 4, h: 2, v: 0
i: 5, h: 1, v: 1
i: 6, h: 1, v: 2
i: 7, h: 1, v: 3
i: 8, h: 2, v: 0
i: 9, h: 2, v: 1
i: 10, h: 2, v: 2
i: 11, h: 2, v: 3
i: 12, h: 3, v: 0
i: 13, h: 3, v: 1
i: 14, h: 3, v: 2
i: 15, h: 3, v: 3
------------------
[...]

((i是访问位置i处的intersection []的循环的计数器,而h和v是coords []数组中包含的i的交点的水平和垂直坐标)

您会注意到,即使我甚至没有使用增量函数访问该数组,每个交集的坐标也会在每个循环后进行修改

this->intersections[curr_int].timeslots[starting_t+travel_t]++;

这是导致此问题的原因。这怎么可能?可能是内存分配问题吗?

1 个答案:

答案 0 :(得分:2)

在这段声明simulation成员的代码中:

intersection intersections [];

intersections是具有柔性数组成员的结构,因此上面的代码尝试创建具有柔性数组成员的结构数组。

这不起作用。具有柔性阵列构件的结构的大小就好像省略了柔性阵列构件(除了可能存在的有关对齐填充的问题)。在计算结构大小或执行数组索引计算时,该编译器无法考虑柔性数组的大小。

此代码尝试将结构数组与灵活的数组成员一起使用:

  

this->交叉点[curr_int] .timeslots [starting_t + travel_t] ++;

在此代码中,编译器无法知道数组this->intersections[curr_int].timeslots有多少个元素。由于timeslots是一个灵活的数组成员,因此intersection的每个实例在其timeslots中可能具有不同数量的元素-程序员的目的是提供所需的任何空间量对于每个实例。由于每个实例的数量可能会有所不同,因此无法将它们排列成固定大小的元素数组,并且编译器无法知道每个实例的大小。

由于编译器不知道程序员打算在每个timeslots中包含多少个元素,因此它不知道每个intersection的大小。在计算this->intersections[curr_int]的地址时,编译器仅使用结构的大小,就像没有弹性数组成员时定义的那样(填充问题除外)。当程序员打算使用灵活的数组成员时,这种计算将是不正确的。

当使用-pedantic开关时,Clang和GCC都会发出警告。

具有灵活数组成员的结构的数组无法工作。您必须为结构使用其他设计。在每个intersection中,timeslots可以是指向时隙数组空间的指针,而不是灵活的数组成员。