C - 如何检查结构的所有必填字段是否都已填满? (最优雅的方法)

时间:2009-11-20 11:36:15

标签: c function structure

我有一个函数,它有一个指向某个结构的指针作为它的参数。如何在函数中检查是否在函数调用之前填充了结构的所有必填字段?

示例:

//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);
}

8 个答案:

答案 0 :(得分:4)

创建一个初始化函数,它将所有字段作为参数(就好像它是一个对象构造函数)并使用它而不是逐个设置字段。

当然,这不会阻止任何人以错误的方式阻止它,但是如果你保持使用该功能的纪律,那么在没有注意到的情况下保留一些未初始化的字段会更加困难。如果您更改结构的字段(以及相应的函数),编译器会在您忘记更新的地方抱怨不匹配的参数。

你可以更进一步(但只是简单的C)用预处理器做一些技巧和包含来强制执行数据封装,但它有点麻烦。任何关于OOP和C的书都会帮助你解决这个问题,但我不知道这些收益是否值得付出。

答案 1 :(得分:2)

您的系统上有valgrind吗?如果您通过它运行程序,它将自动检测任何未初始化变量的使用。它还可以捕获许多其他问题(例如使用已经被释放的内存)。这不会成为程序的永久功能,但它非常适合调试。

我会将它与前面提到的断言和增加的编译器警告结合起来。这就是你能做的所有事情 - 问题是初始化和未初始化的内存之间没有区别。对于机器来说,它们都只是价值观。

答案 2 :(得分:1)

我不认为C本身有解决方案。正如其他人所说,你可以使用valgrind,但这是另一个故事。我总是memset()结构:

memset(&object, 0, sizeof(struct mystruct));

struct mystruct *p = calloc(1, sizeof(struct mystruct));

然后你可以检查成员对0.我相信这是一个好习惯。

答案 3 :(得分:1)

通过静态分析。 Parasoft C++test有BD-PB-NOTINIT(避免使用未初始化的数据)流量分析规则。

答案 4 :(得分:1)

使用断言(来自assert.h)来检查函数所需的先决条件。由您来定义结构字段的有效值或无效值。

示例:

assert( NULL != object);
assert( NULL != object->name);

答案 5 :(得分: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 */

答案 6 :(得分:0)

这通常是通过仔细编程解决的,但如果你必须确定,这里有一个过度的想法:

  • 添加校验和/ crc字段。
  • 添加也修改校验和字段的成员的更新功能。
  • 使用时,使用另一个函数将字段的校验和与校验和字段的校验和进行比较。

答案 7 :(得分:0)

最好的办法是编写一个函数来手动验证结构的内容并返回True / False(但是你定义它),这样你就可以在任何使用这个结构的地方轻松使用该方法。