如何在C中使错误的指针算法更明显?

时间:2018-01-11 21:29:43

标签: c pointers refactoring

我发现了一个错误,其中函数应该传递给指向单个结构的指针,但新代码然后索引指针,导致写出数组的边缘。

void DoTheThing(struct Foo *foo, int index) {
    foo[index].value = bar(index);
}

调用者索引数组并按指定的方式传递指向特定元素的指针:

struct Foo all_the_foos[2];

void DoAllTheThings() {
    for (int i = 0; i < 2; i++) {
        DoTheThing(&all_the_foos[i], i);
    }
}

当然,这是一个错误,因为被调用的函数最终访问all_the_foos[i+i]。有没有办法重构这段代码,以便错误更明显,所以这不会再发生?

1 个答案:

答案 0 :(得分:3)

我无法想到会导致编译器发出警告或错误的任何C语义来帮助你。这留下了人类纪律的替代品。一些想法是:

  • 始终记录功能和文档代码。明确说明输入是什么,有什么要求,结果是什么。这不仅可以避免许多错误,它还可以帮助您在设计中明确设计,使其更好,并编写符合设计的代码。 (必须写一个句子来解释为什么某些东西有效或某些循环或数组的限制会引起你更精确地思考它。这是一个伟大的练习。)

  • 测试。确保函数在其边界和其他任何“有趣”的地方进行测试。(边界包括任何行为即将发生变化。最常见的是,包括索引的最低允许值[因为较低是非法的,所以这是一个变化]和最高允许值,但可能有其他人。)要么运行测试用例,如果代码错误就会报告错误或编写单元测试(特殊代码调用特定函数进行测试,而不运行整个程序)

  • 当它是一个数组时,采用一个声明[]的参数的策略,当它是一个指向单个元素的指针时,采用*。另外,如果指针直接指向所需元素,为什么要传递索引? 例如void DoTheThing(struct Foo *foo)void DoTheThing(struct Foo foo[], int index)

  • 采用始终传递传递的元素数量的策略。传递数组的人传递了元素的总数。传递一个元素的人传递1.然后被调用的函数可以边界检查它使用的任何索引。 (这可能会影响性能,但值得。)