C++ 使用reinterpret_cast将函数强制转换为void*,为什么不';这不违法吗?
这是对我上一个问题的一个切向的跟进。回答者解释说: [C++11]标准没有定义从 “指向函数的指针”指向“指向C++ 使用reinterpret_cast将函数强制转换为void*,为什么不';这不违法吗?,c++,pointers,c++11,language-lawyer,C++,Pointers,C++11,Language Lawyer,这是对我上一个问题的一个切向的跟进。回答者解释说: [C++11]标准没有定义从 “指向函数的指针”指向“指向void的指针” 很难为缺少的东西提供报价,但是 我能做的最接近C++11 4.10/2[conv.ptr]: “指向cv的指针T”类型的PR值,其中T是对象类型,可以转换为“指向cv的指针”类型的PR值 void”。将“指向cvT”的指针转换为 “指向cvvoid”的指针指向存储位置的开始 类型为T的对象所在的位置,就好像该对象是一个most T类型的派生对象(1.8)(即,不是基类子
void
的指针”
很难为缺少的东西提供报价,但是
我能做的最接近C++11 4.10/2[conv.ptr]:
“指向cv的指针T
”类型的PR值,其中T
是对象类型,可以转换为“指向cv的指针”类型的PR值
void
”。将“指向cvT
”的指针转换为
“指向cvvoid
”的指针指向存储位置的开始
类型为T
的对象所在的位置,就好像该对象是一个most
T类型的派生对象(1.8)(即,不是基类子对象)。
空指针值将转换为
目的地类型
(强调矿山)
假设func
被声明为void func()代码>,如果执行C样式转换,即(void*)func
,则转换将成功<代码>静态转换(func)
但是无效,但是重新解释转换(func)
将成功。但是,您不能将随后转换的指针转换回其原始类型。比如说,
罚款:
intmain(){
int*i;
void*s=静态铸件(i);
i=静态铸件;
s=重新解释铸件(i);
i=重新解释铸件;
}
不好:
void func() { }
int main() {
void* s = reinterpret_cast<void*>(func);
reinterpret_cast<decltype(func)>(s);
}
void func(){}
int main(){
void*s=重新解释(func);
重新解释铸件;
}
首先说
[expr.reinterpret.cast]
表达式重新解释(v)
的结果是
将表达式v
转换为类型T
。如果T
是左值
引用类型或函数类型的右值引用,结果为
左撇子;如果T
是对对象类型的右值引用,则结果为
xvalue;否则,结果将是一个prvalue和一个从左值到右值的转换
(4.1)、数组到指针(4.2)和函数到指针(4.3)标准
对表达式v执行转换可以进行的转换
下面列出了使用reinterpret\u cast
显式执行的步骤。不
其他转换可以使用reinterpret\u cast
我把我认为是关键的语言加粗了。最后一部分似乎暗示,如果转换未列出,则是非法的。简言之,允许的转换为:
- 指针可以显式转换为任何足以容纳它的整数类型李>
- 整数类型或枚举类型的值可以显式转换为指针李>
- 函数指针可以显式转换为不同类型的函数指针李>
- 对象指针可以显式转换为不同类型的对象指针
- 有条件地支持将函数指针转换为对象指针类型,或将函数指针转换为对象指针类型李>
- 空指针值(4.10)转换为目标类型的空指针值李>
- 如果
类型的“指向T1
成员的指针”和X
类型都是函数类型或对象类型,则可以将类型为“指向T
类型的Y成员的指针”的PR值显式转换为不同类型的PR值T2
- 如果“指向
的指针”类型的表达式可以使用重新解释转换显式转换为“指向T1
”类型,则类型为T2
的左值表达式可以转换为类型“引用T1
”李>T2
void*
不是函数指针,对象没有函数或void类型
[基本类型]
对象类型是(可能是cv限定的)不是
函数类型,不是引用类型,也不是void类型
所以,也许我是在抓救命稻草,但看来重新解释cast(func)是非法的。但是,另一方面,[expr.static.cast]/5表示“否则,static\u cast
将执行下面列出的转换之一。不得执行其他转换
使用static\u cast
“显式执行,关键区别在于“应”和“可”。这足以使重新解释
合法吗?还是我遗漏了其他内容?(所有引用都来自N3337,并且在N4296之后的每一份草稿中都是等效的,也就是说,这个答案至少对C++11和C++14有效,但对C++03无效,因为这个答案的第一个引用在那里不存在。)
[expr.reinterpret.cast]/8:
将函数指针转换为对象指针类型,或将函数指针转换为对象指针类型
是有条件支持的。这种转换的含义是
定义了实现,除非实现支持
双向转换,将一种类型的PR值转换为
另一种类型和背面,可能具有不同的cv资格,
应产生原始指针值
这包含在您的列表中。您认为void
f = reinterpret_cast<decltype(f)>(s);
f=重新解释铸件;
与源表达式相反,目标类型没有衰减——而且显然不能将void*
强制转换为函数类型。您需要创建目标类型
f = reinterpret_cast<decltype(f)>(s);