【问题标题】:Difference between 'void *' and 'void * (*function)(void *)' initialization, casting, and function pointer calls?'void *' 和 'void * (*function)(void *)' 初始化、强制转换和函数指针调用之间的区别?
【发布时间】:2021-09-29 09:22:24
【问题描述】:

更具体地说,这三个指针在符号表和编译器中是如何工作的?

我的理解是:

void * object 是指向具有未指定类型的对象或函数的指针,基本上需要转换对象才能正确解释,例如(int)object

只要编译器对该对象具有有效的类型信息声明,包括符号表中的存储限定符和说明符,就可以按成员/对象类型进行转换吗?

例如:

void * object;
struct Structure {int member;} Structure;
printf("Object is: %d\n", (Structure->member)(*object));

或者在函数的情况下:

void * (* function)(void *);

我的理解是,对象命名一个指向函数的指针,接受指向未知对象的指针或函数指针,该指针返回指向未知对象或函数指针的指针。函数调用/取消引用不清楚。假设分配给初始化对象声明的 void * 对象应该假定它被初始化的类型。

这些函数指针调用有什么区别?

    struct Structure {void *member;} Structure;
    Structure.member = &main();
    
   /*This assignment, based on my understanding, to Structure.member from main() is supposed to 
    *initialize ember to the type of main() which is assigned automatically or via memcpy()*/

    Structure.member(arg); 
    /*or:*/ 
    Structure.(*(member(arg))); 
    /*or:*/ 
    Structure.(*member(arg))); 

然后这种格式似乎是:

(cast_type) (return_object_type_qualifiers_specifiers)(object_name)(object_parameters);

这个分组是如何工作的?

【问题讨论】:

  • 您在这里似乎有几个问题混合在一起,将它们分开可能会有所帮助。这里有几个 cmets 可以帮助你澄清。
  • (1) 强制转换需要类型名称,而不是表达式,因此(Structure->member)(*object)) 不是强制转换。它将被解析为函数调用,并失败,因为(Structure->member) 的类型为int,而不是指向函数的指针。一些编译器有扩展来让你恢复表达式的类型,例如GCC's typeof,您可以使用它写 (typeof(Structure->member))(*object) 以转换为 int。但是标准 C 没有提供类似的东西。
  • (2) Structure.member = &main();:在函数名后面加上括号总是会导致它被调用。如果你只是想拿函数的地址稍后调用它,写... = &main;或直接写... = main;
  • 感谢您的回复;我不知道 GCC 扩展,也不知道括号的规则是明确的。

标签: c pointers casting structure


【解决方案1】:

void * 不包含有关它指向的对象类型的信息。由程序员来跟踪它并将其转换回正确的指针类型。

在这个例子中:

struct Structure {void *member;} Structure;
Structure.member = &func;

Structure.member 视为一个函数是无效的,因为那不是它的类型。在调用它之前,它需要被转换回正确的函数指针类型。所以如果func被定义为void func(void),你需要这样做:

((void (*)(void))Structure.member)();

此外,也不允许将函数指针转换为对象指针,void * 是对象指针,但是您可能使用的大多数实现仍然支持它。

【讨论】:

  • 谢谢。我对强制转换也有同样的想法,但是我发现我使用的编译器支持对象和函数的通用 void * 引用。
猜你喜欢
  • 2014-09-05
  • 2015-09-26
  • 1970-01-01
  • 2017-12-05
  • 2010-12-16
  • 2018-03-05
  • 1970-01-01
  • 2014-09-09
相关资源
最近更新 更多