C++ 将intptr\t传递给需要int的函数是否安全?
更具体地说,如果我有以下函数指针类型:C++ 将intptr\t传递给需要int的函数是否安全?,c++,c,callback,function-pointers,C++,C,Callback,Function Pointers,更具体地说,如果我有以下函数指针类型: typedef void (*callback_type) (intptr_t context, void* buffer, size_t count); 我是否可以安全且无“未定义行为”地执行以下操作: ? 其中write()是系统调用(编辑:具有签名ssize\u t write(int-fd,const-void*buf,size\u-t count);,因此将int作为第一个参数),而fd是int文件描述符。我假设C和C++的答案是相同的,所以我
typedef void (*callback_type) (intptr_t context, void* buffer, size_t count);
我是否可以安全且无“未定义行为”地执行以下操作:
?
其中
write()
是系统调用(编辑:具有签名ssize\u t write(int-fd,const-void*buf,size\u-t count);
,因此将int
作为第一个参数),而fd
是int
文件描述符。我假设C和C++的答案是相同的,所以我都在标记。< p>问题不是函数之间来回传递参数,因为从一个整型到另一个积分类型自动完成。
问题是,如果intptr\u t
比int
短,那么int
的每个值都不能用intptr\u t
表示,该怎么办?在这种情况下,int
中的一些最高位在转换为intptr\t
时将被截断,因此您最终将write()
写入无效的文件描述符。虽然这不应该调用未定义的行为,但它仍然是错误的。否
这是不可移植的,因为您正在传递一个参数,该参数在通用LP64范例中的大小不同
此外,您没有使用正确的类型取消引用函数指针,并且其结果未定义
现在,正如您所总结的,函数指针将按预期工作,唯一的实际问题是:write(2)如何解释intptr\t
第一个参数
而实际的运行时问题是,在LP64上,您将64位值传递给32位参数。这可能会使后续参数不对齐。在带有寄存器参数的系统上,它可能工作得很好。让我们看看C标准 C11(n1570),§6.3.2.3指针 指向一种类型函数的指针可以转换为指向 功能的另一种类型,并再次返回;结果应进行比较 等于原始指针。如果使用转换的指针调用 其类型与引用类型不兼容的函数 行为是未定义的 C11(n1570),§6.7.6.3功能声明器(包括原型) 对于要兼容的两种功能类型,两者均应规定兼容 返回类型。此外,参数类型列表(如果两者都存在), 应在参数数量和省略号的使用上达成一致 终结者;相应参数应具有兼容类型 C11(n1570),§6.2.7兼容型和复合型 如果两种类型的类型相同,则它们具有兼容的类型 结论:
void (*) (intptr_t context, void* buffer, size_t count);
无法转换为:
void (*) (int context, void* buffer, size_t count);
你的要求似乎与标题的要求相反。编辑:啊,系统调用采用
int
。嗯,context
属于intptr\u t
类型,正在传递给write
,该类型需要int
。对我来说似乎是对的…嗯?此时,您正在将intptr\u t
传递给需要intptr\u t
的函数。那么问题出在哪里呢?你担心的部分是什么?从&write
到callback\u type
的转换,从fd
到intptr\t
的转换,或者其他什么?@lvella您没有解释write
将int
作为其第一个参数。对func\u ptr
的赋值是否正确编译?如果是这样,那么在您的计算机上,intptr\t
必须是int
,否?@sftrabbit:赋值涉及重新解释强制转换,因此它将编译转换是否有效。如果intptr\u t
不是int
,你会得到未定义的行为。intptr\u t
的要点不就是能够同时容纳int
和指针吗?@lvella要点是它是一个整数类型,保证足够大,可以容纳指针。但是不能保证它能保存什么类型的整数。保证类型本身是一个整数type@lvella据我所知,intptr\u t
是一种保证能够容纳指针的整数类型,而不是其他类型。标准中是否有要求sizeof(T*)@H2CO3的要求?我不知道。@sftrabbit谢谢。对,那么这是一个真正的问题。
void (*) (int context, void* buffer, size_t count);