C 强制转换函数指针void的效果如何?

C 强制转换函数指针void的效果如何?,c,struct,function-pointers,void-pointers,function-prototypes,C,Struct,Function Pointers,Void Pointers,Function Prototypes,所以我第64次尝试编写一个缓冲库,我开始学习一些非常高级的东西。我想我需要一些关于这方面的专业意见 在我的第一个头文件中,我有: typedef struct StdBuffer { void* address; } StdBuffer; extern void StdBufferClear(StdBuffer); typedef struct CharBuffer { char* address; } CharBuffer; void (*CharBufferClear)(CharBuffe

所以我第64次尝试编写一个缓冲库,我开始学习一些非常高级的东西。我想我需要一些关于这方面的专业意见

在我的第一个头文件中,我有:

typedef struct StdBuffer { void* address; } StdBuffer;
extern void StdBufferClear(StdBuffer);
typedef struct CharBuffer { char* address; } CharBuffer;
void (*CharBufferClear)(CharBuffer) = (void*) StdBufferClear;
在另一个包含第一个头文件的头文件中,我有以下内容:

typedef struct StdBuffer { void* address; } StdBuffer;
extern void StdBufferClear(StdBuffer);
typedef struct CharBuffer { char* address; } CharBuffer;
void (*CharBufferClear)(CharBuffer) = (void*) StdBufferClear;
声明此函数指针无效会干扰调用吗?它们具有按值匹配的签名。我以前从未见过函数指针被声明为void,但这是让它干净编译的唯一方法

从堆栈角度看,它与我在汇编程序编码中所学到的应该没有任何区别

无关紧要的天哪!我刚才说Stackwise在StackOverflow上

嗯。。看来我在这里假设得太多了。如果可以的话,请允许我隐居。我不在乎地址中存储的是什么“类型”的数据。我所关心的只是一个“单元”的大小以及地址上有多少个单元。如果您愿意:

typedef struct StdBuffer {

    size_t width;        ///< The number of bytes that complete a data unit.
    size_t limit;        ///< The maximum number of data units that can be allocated for this buffer.
    void * address;      ///< The memory address for this buffer.
    size_t index;        ///< The current unit position indicator.
    size_t allocated;    ///< The current number of allocated addressable units.
    StdBufferFlags flags;///< The API contract for this buffer.

} StdBuffer;

不,使用什么数据类型来存储数据并不重要。它只关系到C用来读写数据的类型,以及数据是否足够大。

不,不管使用什么数据类型来存储数据。只有C型用于读写该数据,且数据大小足够时,才重要。

此代码需要诊断:

void (*CharBufferClear)(CharBuffer) = (void*) StdBufferClear;
您正在将
void*
指针转换为不带强制转换的函数指针。在C语言中,
void*
指针可以转换为指向对象类型的指针,而无需转换为函数指针类型。(在C++中,需要一个强制转换来将<代码>空白> /COD>转换为对象类型,以增加安全性。 这里您只需要在函数指针类型之间转换,即:

void (*CharBufferClear)(CharBuffer) = (void (*)(CharBuffer)) StdBufferClear;
然后你仍然在做同样的类型双关,因为函数是不同的类型。您正试图使用指向接受
CharBuffer
的函数的指针来调用接受
StdBuffer
的函数

这种类型的代码不是定义良好的C。在击败了类型系统之后,你只能依靠自己,依靠测试、检查目标代码,或者从编译器编写者那里获得某种保证,这种事情可以与编译器一起工作

您在汇编代码中学到的东西并不适用,因为汇编语言只有少量的基本数据类型,如“机器地址”或“32位字”。具有相同布局和低级表示的两个数据结构可能是不兼容类型的概念在汇编语言中并不存在


即使两种类型在低级别上看起来相同(另一个示例:
unsigned int
unsigned long
有时完全相同),C编译器也可以基于没有违反类型规则的假设来优化程序。例如,假设
A
B
指向相同的内存位置。如果为对象分配了
A->member
,如果
A->member
B->member
具有不兼容的类型,例如一个是
char*
,另一个是
void*
,则C编译器可以假定对象
B->member
不受此影响。生成的代码将保持在寄存器中缓存
B->member
的旧值,即使内存中的副本被
a->member
的赋值覆盖。这是一个无效别名的示例。

此代码需要诊断:

void (*CharBufferClear)(CharBuffer) = (void*) StdBufferClear;
您正在将
void*
指针转换为不带强制转换的函数指针。在C语言中,
void*
指针可以转换为指向对象类型的指针,而无需转换为函数指针类型。(在C++中,需要一个强制转换来将<代码>空白> /COD>转换为对象类型,以增加安全性。 这里您只需要在函数指针类型之间转换,即:

void (*CharBufferClear)(CharBuffer) = (void (*)(CharBuffer)) StdBufferClear;
然后你仍然在做同样的类型双关,因为函数是不同的类型。您正试图使用指向接受
CharBuffer
的函数的指针来调用接受
StdBuffer
的函数

这种类型的代码不是定义良好的C。在击败了类型系统之后,你只能依靠自己,依靠测试、检查目标代码,或者从编译器编写者那里获得某种保证,这种事情可以与编译器一起工作

您在汇编代码中学到的东西并不适用,因为汇编语言只有少量的基本数据类型,如“机器地址”或“32位字”。具有相同布局和低级表示的两个数据结构可能是不兼容类型的概念在汇编语言中并不存在


即使两种类型在低级别上看起来相同(另一个示例:
unsigned int
unsigned long
有时完全相同),C编译器也可以基于没有违反类型规则的假设来优化程序。例如,假设
A
B
指向相同的内存位置。如果为对象分配了
A->member
,如果
A->member
B->member
具有不兼容的类型,例如一个是
char*
,另一个是
void*
,则C编译器可以假定对象
B->member
不受此影响。生成的代码将保持在寄存器中缓存
B->member
的旧值,即使内存中的副本被
a->member
的赋值覆盖。这是一个无效别名的示例。

标准没有定义将函数指针强制转换为
void*
的结果


同样,在函数指针之间转换,然后通过错误的指针调用也是未定义的行为。

标准没有定义将函数指针强制转换为void的结果*<