动态类型选择是否会破坏C中的严格别名?

时间:2014-07-27 18:23:29

标签: c strict-aliasing

我们说我有一些看起来像这样的代码:

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 *转换为各种不同的类型 从...开始。

1 个答案:

答案 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的指针,然后再返回,结果将与原始指针进行比较。

所以,重复一遍,转换始终是允许的,但无论如何都没用。