【问题标题】:Updating a variable's value in a struct cause another variable from the same struct to be modified更新结构中的变量值会导致同一结构中的另一个变量被修改
【发布时间】:2019-05-07 09:08:26
【问题描述】:

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

基本上我遇到的问题是一个结构数组,其中每个结构包含 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 的交点[] 的循环的计数器,而 h 和 v 是 coords[] 数组中包含的交点 i 的水平和垂直坐标)

如您所见,即使我什至没有使用递增函数访问该数组,某些交叉点的​​坐标也会在每个周期后修改

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

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

【问题讨论】:

  • 分配给timeslots的内存在哪里?
  • 您的 malloc 调用几乎肯定是错误的。除了创建一个包含灵活数组成员的灵活数组成员,你不能稍微简化一下结构吗?
  • @P.W 在 malloc 的这一部分:(sizeof(intersection)*(h_streets*v_streets)*(sizeof(int)*(max_time+1001))) 基本上我为每个交叉点分配(sizeof(int)*(max_time+1001)) (sizeof(intersection)*(h_streets*v_streets)
  • 灵活的数组成员不能解决这个问题。事实上,您已经编写了一个 malloc 调用,它变得如此复杂,以至于您自己甚至无法理解它。所以你的代码不可读或不简单。也许你真正想要的是一个查找表——一个指针数组,每个指针指向一个可变大小的数组。
  • 您不能创建包含 FAM 的结构数组。 C11 Standard - 6.7.2.1 Structure and union specifiers(p3)

标签: c struct malloc flexible-array-member


【解决方案1】:

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

intersection intersections [];

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

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

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

this->intersections[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 可以是指向时隙数组空间的指针,而不是灵活的数组成员。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-29
    • 2021-12-18
    • 1970-01-01
    • 2022-01-01
    • 2011-09-09
    • 1970-01-01
    相关资源
    最近更新 更多