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

Updating a variable's value in a struct cause another variable from the same struct to be modified

我正在研究一个代码,它可以处理一段时间内十字路口的交通情况,以及 returns 给定时间十字路口的交通量。

基本上我遇到的问题是一个结构数组,其中每个结构包含 2 个向量:一个具有交叉点坐标 (x, y),另一个跟踪在时间 t 有多少辆汽车通过该交叉路口( 0到n的每一个slot代表时间,里面的值是当时通过的车数)。

结构如下:

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]++;

修改坐标数组的值。

这是在每个循环中仅打印出交叉点坐标的示例:

------------------
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的intersections[]的计数器,而h和v是coords[]数组中包含的交叉点i的水平和垂直坐标)

正如您所注意到的,一些交叉点的​​坐标在每个循环后都会被修改,即使我什至没有使用递增函数访问该数组

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

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

在声明 simulation 成员的代码中:

intersection intersections [];

intersections 是一个具有灵活数组成员的结构,因此上面的代码试图创建一个具有灵活数组成员的结构数组。

这行不通。具有灵活数组成员的结构的大小就像省略了灵活数组成员一样(除了关于对齐填充的潜在问题)。此编译器在计算结构大小时或执行数组索引计算时无法考虑灵活数组的大小。

此代码尝试使用具有灵活数组成员的结构数组:

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

在这段代码中,编译器无法知道数组 this->intersections[curr_int].timeslots 有多少个元素。由于 timeslots 是一个灵活的数组成员,intersection 的每个实例在其 timeslots 中可能有不同数量的元素——目的是让程序员提供任意数量的 space 每个实例都需要。由于每个实例的数量可能不同,因此无法将它们排列成 fixed-size 个元素的数组,并且编译器无法知道每个实例有多大。

因为编译器不知道程序员打算在每个 timeslots 中有多少个元素,所以它不知道每个 intersection 有多大。计算 this->intersections[curr_int] 的地址时,编译器仅使用结构的大小,就像在没有灵活数组成员的情况下定义的一样(填充问题除外)。当程序员希望存在灵活的数组成员时,此计算将不正确。

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

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