0

我正在研究一个代码,它随着时间的推移处理十字路口的交通并返回给定时间十字路口的交通量。

基本上我遇到的问题是一个结构数组,其中每个结构包含 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))) );

在读取有关汽车从一个位置到另一个位置的行程的数据时,如前所述,我所做的是,当汽车当时穿过那个十字路口时,将 timeslots[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]++;

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

4

1 回答 1

2

在此声明成员的代码中simulation

intersection intersections [];

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

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

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

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

在这段代码中,编译器无法知道数组有多少元素this->intersections[curr_int].timeslots。由于timeslots是一个灵活的数组成员,因此 an 的每个实例中intersection可能有不同数量的元素timeslots- 目的是让程序员为每个实例提供所需的任意数量的空间。因为这个数量可能随每个实例而变化,所以它们不能排列成一个固定大小的元素数组,编译器也无法知道每个元素有多大。

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

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

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

于 2019-05-07T11:54:19.247 回答