我们说我有一些看起来像这样的代码:
void foo(void* obj, int type)
{
TypeA* a = (TypeA*)obj;
TypeB* b = (TypeB*)obj;
TypeC* c = (TypeC*)obj;
if( type == 1 ) {
// code that uses "a"
}
else if( type == 2 ) {
// code that uses "b"
}
else if( type == 3 ) {
// code that uses "c"
}
}
我很想知道这个函数是否会破坏严格的别名a
先验,或者函数的有效性取决于它实际使用的方式。
我的某些部分希望如果我这样做,事情会好起来的
曾经使用过foo(&objectOfTypeA, 1)
,foo(&objectOfTypeB, 2)
这个函数,
或foo(&objectOfTypeC, 3)
。但我只知道a的别名错误
几天,所以我担心函数foo()
是正确的
开始只是因为它将传入的void *转换为各种不同的类型
从...开始。
答案 0 :(得分:3)
这不会破坏严格的别名,因为您只能通过正确的类型访问*obj
。转换obj
不会导致访问*obj
。
严格别名仅适用于访问对象,而不适用于指针操作。 您可以随意操作指针。
从n1570§6.5¶7
对象的存储值只能由具有以下类型之一的左值表达式访问...
由于您未访问*obj
而只访问obj
,因此不会违反严格别名规则。
这里的第二个问题是转换是否允许。答案是肯定的,因为您可以将void *
转换为任何其他对象指针类型。 void
类型是特殊的,它是唯一具有此属性的类型。
int *i;
void *ptr = &i;
float *f = ptr; // Permissible
标准没有说明f
的价值是什么。换句话说,虽然转换是允许的,但您对f
没有任何用处。您甚至无法将其转换回void *
。
这在n1570§6.3.2.3¶1中解释:
指向
void
的指针可以转换为指向任何对象类型的指针。指向任何对象类型的指针可以转换为指向void
的指针,然后再返回,结果将与原始指针进行比较。
所以,重复一遍,转换始终是允许的,但无论如何都没用。