我有一个函数,它有一个指向某个结构的指针作为它的参数。如何在函数中检查是否在函数调用之前填充了结构的所有必填字段?
示例:
//lib.c
void f(X_type *x)
{
...
}
//user.c
main(){
X_type object;
object.name = "I am X";
object.ID = 1;
...
f(X_type &object);
}
答案 0 :(得分:4)
创建一个初始化函数,它将所有字段作为参数(就好像它是一个对象构造函数)并使用它而不是逐个设置字段。
当然,这不会阻止任何人以错误的方式阻止它,但是如果你保持使用该功能的纪律,那么在没有注意到的情况下保留一些未初始化的字段会更加困难。如果您更改结构的字段(以及相应的函数),编译器会在您忘记更新的地方抱怨不匹配的参数。
你可以更进一步(但只是简单的C)用预处理器做一些技巧和包含来强制执行数据封装,但它有点麻烦。任何关于OOP和C的书都会帮助你解决这个问题,但我不知道这些收益是否值得付出。
答案 1 :(得分:2)
您的系统上有valgrind吗?如果您通过它运行程序,它将自动检测任何未初始化变量的使用。它还可以捕获许多其他问题(例如使用已经被释放的内存)。这不会成为程序的永久功能,但它非常适合调试。
我会将它与前面提到的断言和增加的编译器警告结合起来。这就是你能做的所有事情 - 问题是初始化和未初始化的内存之间没有区别。对于机器来说,它们都只是价值观。
答案 2 :(得分:1)
使用断言(来自assert.h)来检查函数所需的先决条件。由您来定义结构字段的有效值或无效值。
示例:
assert( NULL != object);
assert( NULL != object->name);
答案 3 :(得分:1)
在结构中添加另一个成员以指示其余成员是否已填充(并将其初始化为“false”)。然后检查一下这个新成员。
struct whatever {
int datagood;
/* more members; */
};
struct whatever bar;
bar.datagood = 0;
foo(&bar); /* foo() will see datagood == 0 */
/* bar.a = 42; */
/* bar.b = 24; */
bar.datagood = 1;
foo(&bar); /* foo() will see datagood == 1 */
答案 4 :(得分:1)
我不认为C本身有解决方案。正如其他人所说,你可以使用valgrind,但这是另一个故事。我总是memset()结构:
memset(&object, 0, sizeof(struct mystruct));
或
struct mystruct *p = calloc(1, sizeof(struct mystruct));
然后你可以检查成员对0.我相信这是一个好习惯。
答案 5 :(得分:1)
通过静态分析。 Parasoft C++test有BD-PB-NOTINIT(避免使用未初始化的数据)流量分析规则。
答案 6 :(得分:0)
最好的办法是编写一个函数来手动验证结构的内容并返回True / False(但是你定义它),这样你就可以在任何使用这个结构的地方轻松使用该方法。
答案 7 :(得分:0)
这通常是通过仔细编程解决的,但如果你必须确定,这里有一个过度的想法: