2011-08-15 18 views
13

以下代碼是否會調用未定義的行爲(由於別名違規或其他原因)?數組指針別名 - 未定義的行爲?

int foo(int (*a)[10], int (*b)[5]) 
{ 
    (*a)[5]++; 
    return (*b)[0]; 
} 

int x[10]; 
foo(&x, (int (*)[5])&x[5]); 

注意,使用普通int *而不是指針到數組類型對應的代碼將是完全合法的,因爲ab將指向同一類型且因此允許別名彼此。

編輯:有趣的結果,如果這其實就是一個混疊違規,是它似乎是一個hackish的,但有效的方式來獲得restrict語義預C99。如:

void some_func(int *aa, int *bb) 
{ 
    int (*a)[1] = (void *)aa; 
    int (*b)[2] = (void *)bb; 
    /* Now **a and **b can be assumed by the compiler not to alias */ 
} 

據推測,如果你需要在每個地址來訪問實際的數組,可以使用SIZE_MAX-1和SIZE_MAX-2等爲不同的尺寸。

+1

它們是指向相同類型的指針,它們不能被假定爲別名。 –

回答

4

你是不是通過不同類型這裏指針訪問對象:你是不是操縱對象數組到ab點本身,而是對象由(*a)+5(*b)+0,即*((*a)+5)*((*b)+0)指出。由於這些是指向相同類型的指針,因此它們可能會混淆同一個對象。

++操作隱含的分配是一個有效的分配對象指向(*b)+0++相當於x = x + 1(除了x被評估一次),以及簡單的分配=標準說

如果存儲在一個對象中的值是從另一個對象中讀取的,該對象以任何方式與第一個對象的存儲重疊,那麼重疊應該是精確的,並且這兩個對象應該具有合格的或不合格的兼容的版本t0。 YPE;否則,行爲是未定義的 。

這裏的類型完全相同,重疊是準確的。

+0

+1非常有趣。雖然,我仍然討厭所有這些指針語義的東西...... –

+0

通過這個邏輯,不會訪問'int [5] [5]'和疊加的int [25]'也是有效的......? –

+0

@R ..是的,我認爲這是有效的。陣列以某種方式處於灰色區域。對於一個'struct'來說,顯然訪問一個字段'toto.x'作爲一個整體訪問該對象,'A [24]'和'B [4] [4]'由指針算術定義,因此決不會訪問數組作爲一個整體。 –