c-函数参数使用不一致,没有编译器警告



在对不想在目标硬件上运行的软件进行C代码审查期间,在功能使用中发现以下不一致:

软件组件1实现以下功能:

void foo(uint8 par_var[2])

函数foo()还写入par_var阵列的两个元素。

SW组件2获得foo()的外部声明,如下所示

extern void foo(uint8 *par_var)

并按如下方式使用:

uint8 par_var;
foo(&par_var); //-> sending a pointer to a scalar
//   instead to an array of 2 elements.

显然,它可能导致程序失败,而且实际上也会导致程序失败。

问题是,例如,编译器/链接器是否可以通过发出警告来拦截不一致性。

我已经扫描并尝试了一些gcc(CygWin)编译器选项以及标准选项(-Wall,-pedantic)https://gcc.gnu.org/onlinedocs/gcc-3.4.4/gcc/Warning-Options.html

但找不到可以发出相应警告的。

有一个C功能可以帮助编译器诊断这种情况,但我不知道有哪个编译器会利用它并发出警告。如果foo被声明为void foo(uint8 par_var[static 2]);,那么调用方需要根据C 2018 6.7.6.3 7:将指针传递到至少两个元素

如果关键字static也出现在数组类型派生的[]中,则对于函数的每次调用,相应实际参数的值应提供对数组的第一个元素的访问,该数组的元素数至少与size表达式指定的元素数相同。

因此,看到uint8 par_var; foo(&par_var);的编译器可以识别传递两个元素的失败并提供警告。(虽然我不知道编译器会检查声明的大小,但当为这样的参数传递空指针时,一些编译器会发出警告。)

众所周知,在声明void foo(uint8 par_var[2])中,par_var被自动调整为uint8 *par_var。作为替代方案,您可以通过将foo声明为void foo(uint8 (*par_var)[2]);来将指针传递给uint8的数组,而不是将指针传递到uint8

然后你必须给它传递一个数组,比如:

uint8 A[2];
foo(&A);

如果用指向uint8的指针调用它,编译器应该发出警告。不幸的是,这也限制了常规;必须向其传递一个指向两个uint8的数组的指针,而不能向其传递指向较大数组的指针或指向较大数组中的uint8的指针。因此,它的用途有限。尽管如此,它在某些情况下也可以发挥作用。

最新更新