c - 函数参数使用不一致不会导致编译器警告
问题描述
在对不想在目标硬件上运行的软件进行 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
但找不到可以发出相应警告的。
解决方案
有一个 C 功能可以帮助编译器进行诊断,但我不知道编译器会利用它并发出警告。如果foo
被声明为void foo(uint8 par_var[static 2]);
,则根据 C 2018 6.7.6.3 7,调用者需要将指针传递给至少两个元素:
如果关键字
static
也出现在数组类型派生的[
and]
中,则对于函数的每次调用,对应的实际参数的值应提供对数组的第一个元素的访问,该数组的元素至少与大小指定的一样多表达。
因此,编译器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
中的 a 的指针传递给它。所以它的用途有限。尽管如此,它可以在某些情况下发挥作用。
推荐阅读
- reactjs - firebase 的 onAuthStateChanged 如何在 reactJS 的 ComponentDidMount 生命周期中工作
- ssms - 如何使用样式代码 104 将字符串转换为日期类型?
- haskell - 在 Haskell 中定义 letrec 实现小语言的表达式
- unit-testing - 如何在不明确传递所有模拟类的情况下对颤振进行单元测试?
- python - Python中的性能度量计算
- python - TensorFlow2:占位符只接受关键字参数
- javascript - 使用 Socket.io/React/Node 管理聊天历史
- three.js - AFrame 指定 WebGL 版本
- node.js - 在 Node.js 的其他模块中通过引用使用数组是否绝对是这种情况?
- python - 如何在数组数组中巧妙地转换 Pandas Dataframe?