使用不一致的函数参数不会产生编译器警告

时间:2019-01-23 13:11:40

标签: c function pointers gcc parameters

在不希望在目标硬件上运行的软件的C代码检查中,在功能使用中发现了以下不一致之处:

SW组件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

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

1 个答案:

答案 0 :(得分:5)

有一个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。另外,您也可以通过将uint8声明为uint8来传递指向foo的数组的指针,而不是传递指向void foo(uint8 (*par_var)[2]);的指针。

然后,您必须将其传递给数组,例如:

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

如果使用指向uint8的指针进行调用,则编译器应发出警告。不幸的是,这也限制了例程。您必须将指向两个uint8的数组的指针传递给它,而不能将指向更大数组的指针或指向更大数组中的uint8的指针传递给它。因此它的使用受到限制。尽管如此,它仍可以在某些情况下使用。