繁体   English   中英

如何验证作为无效指针传递给函数的值的类型?

[英]how to verify the type of a value passed to a function as void pointer?

具有以下代码:


文件:types.h

typedef struct Struct_A_T
{
   int   A;
   char  B;
   float C;
}Struct_A;

文件:code.c

#include "types.h"

void Function(const void *const ptr)
{
   Struct_A localStruct = *((Struct_A *)ptr);

   localStruct.A = 1000;
   localStruct.B = 250;
   localStruct.C = 128.485;
}

文件:main.c

#include "types.h"

void Function(const void *const ptr);

int main(void)
{
   Struct_A MyStruct1 = {2, 5, 2.8};
   float local = 24.785;

   /* Correct call */
   Function(&MyStruct1);

   /* Incorrect call!!! */
   Function(&local);
}

并且知道指向void的指针可以用作“通用”指针。 我如何在“函数”内部检测到在void指针中传递的类型是正确的,以避免在文件main.c中最后一次调用引起的运行时错误?

使用语言功能无法做到这一点。 只能手动完成。

我首先在代码的调试版本中使用以下技术

typedef struct Struct_A_T
{
   int   A;
   char  B;
   float C;
#ifdef DEBUG
   unsigned signature; 
#endif /* DEBUG */
}Struct_A;

即在调试配置中,我在结构中引入了一个附加字段。 该结构类型的每个对象都必须使用专用于此类型的某些预定“不可预测”签名值来初始化该字段,例如

#define STRUCT_A_SIGNATURE 0x12345678

如果所有结构都以某种集中方式创建(例如动态分配或由专用功能初始化),则这样做很容易。 如果没有这样的集中位置,这可能会比较麻烦。 但这是我们有时必须为安全付出的代价。 例如,在您的示例情况下,

Struct_A MyStruct1 = {2, 5, 2.8, 0x12345678 };

顺便说一句,指定的初始化程序可能会使此类初始化更加稳定并且更易于阅读。

然后,为了将指针从void *转换为特定类型,我使用以下强制转换宏

#ifdef DEBUG
  #define TO_STRUCT_A(p)\
    (assert((p) == NULL || ((Struct_A *)(p))->signature == STRUCT_A_SIGNATURE),\
      (Struct_A *)(p))
#else /* DEBUG */
  #define TO_STRUCT_A(p) ((Struct_A *)(p))
#endif /* DEBUG */

意味着您可以在Function内执行

Struct_A localStruct = *TO_STRUCT_A(ptr);

如果将错误类型的指针传递给Function ,则很有可能触发断言失败。

当然,所有这些都可以(并且应该)使用更通用的宏来实现。

显然,这仅适用于结构类型,您可以在其中注入该附加签名字段。 这种方法的另一个潜在问题是,通过在调试版本的结构中引入额外的字段,可能会导致调试行为和发布版本的行为发生分歧。

您不能,这是void*的主要缺点,您无法确定要指向的内容。 您只需要知道

您可以使用sizeof将结构的大小与void*指向的sizeof进行比较。 将指向您的struct类型的指针传递给Function并不是一个充分但必要的条件。 顺便说一句,语言的属性可以检查变量的元数据(包括类型),并且范围更广,这称为反射 它可用许多现代语言提供,并且C ++ 11中最近包含了一些功能,但是C仍然缺少它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM