【问题标题】:Function pointer cast on function with inherited C structure函数指针强制转换为具有继承的 C 结构的函数
【发布时间】:2021-12-27 18:06:28
【问题描述】:

如果在示例函数转换中出现并且调用在 C 中有效,我正在寻找答案(如果没有任何示例,如何获得类似的行为会很好)。

例子:

#include <stdio.h>
#include <stdint.h>

typedef struct {
    uint32_t a;
} parent_t;

typedef struct {
    parent_t parent;
    uint32_t b;
} child_t;


typedef void (*funct_ptr_t)(parent_t* pParent, uint32_t x);

void test_function(child_t* pChild, uint32_t x);

int main()
{ 
    funct_ptr_t func = (funct_ptr_t)test_function;
    funct(NULL, 0U);

    return 0;
}

void test_function(child_t* pChild, uint32_t x) {
    // do something
}

@编辑 如上无效,我也想问一下第二种方法

typedef void (*funct_ptr_t)(void* pChild, uint32_t x);

void test_function(child_t* pChild, uint32_t x);

int main()
{ 
    funct_ptr_t func = (funct_ptr_t)test_function;
    child_t child;
    func(&child, 0U);

    return 0;
}

void test_function(child_t* pChild, uint32_t x) {
    // do something
}

【问题讨论】:

  • 这至少看起来很危险 - 该函数需要一个指向 child_t 对象的指针,但可能会收到一个“仅”指向 parent_t 的指针。如果该函数随后尝试访问 b 成员,您肯定会调用 undefined behavior
  • 相反的做法是安全的,因为该函数不会尝试访问 parent 前缀。

标签: c language-lawyer


【解决方案1】:

这是无效的。

只能通过兼容的函数指针类型调用函数。为了使两个函数指针类型兼容,对应的参数必须具有兼容的类型并且返回类型必须兼容。

test_function 的类型为 void (*)(child_t*, uint32_t ),但正在通过类型为 void (*)(parent_t*, uint32_t ) 的函数指针调用。这意味着正在通过不兼容的类型调用该函数,并且这样做会触发 undefined behavior

如果您尝试为第一个参数接受指向不同类型的指针,处理此问题的最简单方法是将函数和函数指针的第一个参数的类型更改为void *,然后执行函数内部的必要转换。

另一种选择是将第一个参数的类型更改为test_functionparent_t * 并在函数内部执行强制转换。这将起作用,因为指向结构的指针可以转换为指向其第一个成员的指针,因此您可以这样做:

void test_function(parent_t* pChild, uint32_t x);

int main()
{ 
    funct_ptr_t func = (funct_ptr_t)test_function;
    child_t c;
    funct((parent_t *)&c, 0U);

    return 0;
}

void test_function(parent_t* p, uint32_t x) {
    child_t *p_Child = (p_Child *)p;
    // do something
}

【讨论】:

  • C 2018 6.2.5 28 表示所有指向结构类型的指针都应具有相同的表示和对齐要求,注释 49 表示这意味着作为函数参数的可互换性。 “可互换性”并未在 C 标准中正式指定,但似乎这种可互换性旨在覆盖兼容性问题,并且从未在标准中阐明。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-20
  • 2018-03-05
  • 2020-11-22
相关资源
最近更新 更多