次の例を検討してください。
typedef struct test_flex_arr{
size_t sz;
struct {
int i;
const char *path;
} info[];
} tfa;
int main(void){
size_t sz = 100;
tfa *ptr = malloc(sizeof *ptr + sizeof (*((tfa*) NULL)).info[sz]);
ptr->info[99].i = 10;
printf("%d\n", ptr->info[99].i); //prints 10
}
このプログラムはクラッシュするだろうと思っていましたが、問題なく動作します。指定された6.5.3.4(p2)
とおり:
この
sizeof
演算子は、そのオペランドのサイズ (バイト単位) を返します。これは、式または括弧で囲まれた型の名前の場合があります。サイズは、オペランドの型から決定されます。結果は整数です。オペランドの型が可変長配列型の場合、オペランドは評価されます。それ以外の場合、オペランドは評価されず、結果は整数定数になります
のオペランドの型sizeof ((*((tfa*) NULL)).info)[sz]
は可変長配列であるため、オペランドを評価する必要があります。しかし、オペランドの評価は、NULL
クラッシュにつながると予想していた逆参照を意味します。
コードの動作は明確に定義されていますか?