下面,我在C中定义了一个Map
结构。 它的功能是地图,具有setValue
和getValue
功能。 键值默认为 -1。
typedef struct {
int key;
int value;
} Index;
typedef Index Map[1000];
void initMap(Map *map)
{
for (int i = 0; i < 1000; i++)
{
Index thisIndex = *map[i];
thisIndex.key = -1;
thisIndex.value = 0;
}
}
int getValue(Map *map, int keyToGet)
{
for (int i = 0; i < 1000; i++)
{
Index thisIndex = *map[i];
if (thisIndex.key == keyToGet)
{
return thisIndex.value;
break;
}
}
return -1;
}
void setValue(Map *map, int keyToSet, int valueToSet)
{
int set = 0;
for (int i = 0; i < 1000; i++)
{
Index thisIndex = *map[i];
if (thisIndex.key == keyToSet)
{
thisIndex.value = valueToSet;
set = 1;
break;
}
}
if (set == 1)
return;
for (int i = 0; i < 1000; i++)
{
Index thisIndex = *map[i];
if (thisIndex.key == -1)
{
thisIndex.key = keyToSet;
thisIndex.value = valueToSet;
break;
}
}
}
int findValue(Map *map, int valueToGet)
{
for (int i = 0; i < 1000; i++)
{
Index thisIndex = *map[i];
if (thisIndex.value == valueToGet)
return thisIndex.key;
}
return -1;
}
在代码中的某个时刻,当运行时,我得到一个SegFault,大概是为了访问或试图覆盖我没有管辖权的内存。 我的问题是,这是在哪里发生的? 哪个功能可以做到这一点,在哪里? 我已经筛选了多次,但我似乎找不到会在哪里发生。
代码中有两个主要错误。
首先,将 typedefMap
键入到数组。这意味着当你有一个这样的函数原型时:
int getValue(Map *map, int keyToGet);
你真的会得到这样的东西:
int getValue(Index (*map)[1000], int keyToGet);
在 C 语言中,定义模仿使用,因此您应该像这样访问映射元素:
Index thisIndex = (*map)[i];
你使用它的方式,*map[i]
等同于 *(map[i]),并且要求数组是一个包含 1,000 个指向Index
的指针的数组,但事实并非如此。
(*map)[i]
sytnax 很复杂,你不需要它。因为Map
是一个数组,所以它会衰减为指向其第一个元素的指针。如果要修改元素,则无需传递指向数组的指针。将指针传递给第一个元素就足够了,在您的情况下,该元素可以是以下任一元素:
int getValue(Map map, int keyToGet);
int getValue(Index map[], int keyToGet);
int getValue(Index *map, int keyToGet);
然后访问数组的元素就map[i]
了。
修复该修复可以修复您的分割错误,但不能修复地图不起作用的事实。当您分配给如下结构时:
Index thisIndex = map[i];
然后修改thisIndex
,你不会修改你map
中的任何内容!在这里,thisIndex
是一个副本。当thisIndex
超出范围时,所有修改都将丢失。
您可以直接使用map
:
if (map[i].key == keyToSet) {
map[i].value = valueToSet;
return;
}
(你为什么不呢?thisIndex
比map[i]
长),或者您可以thisIndex
指向数组元素的指针:
Index *thisIndex = &map[i];
if (thisIndex->key == keyToSet) {
thisIndex->value = valueToSet;
return;
}
在这里,您可以通过指针访问和修改map[i]
字段。
在 typedef 中隐藏数组可能不是一个好主意。也许有一次您希望将活动项目的数量保留在数组旁边。(这将使您的代码更有效率,因为在最坏的情况下,您不必遍历所有 1,000 个项目。在这种情况下,您可以Map
创建一个包含 1000 个键/值对和一个计数的数组的结构。然后,您必须将指针传递给结构类型,以便您可以更新字段。这是作为练习留下的...:)