Cにおけるラベル直後の変数宣言とswitch

void hoge0(int v)
{
	//{} がない switch, 分岐が1つだけで使い物にならない
	switch(v)
	label: break;
	
	//{} がないので label は有効
	goto label;
}

void hoge1(int v)
{
	//{} がある switch 
	switch(v){
	case 1: break;
	label: break;
	}
	
	//label: は switch{} のそとでも使える (なんで?)
	goto label;
}

int hoge2(int v)
{
	switch(v){
	case 1: //error, case x:, label: の直後に変数宣言はできない
		int i = 0;
		break;
	label: break;
	}
	return i;
}

int hoge3(int v)
{
	switch(v){
	case 1: ; //ダミーの ; をいれれば変数宣言は通る
		int i = 0;
		break;
	label: 
		i = 2; //i は有効
		break;
	}
	//error, i の有効範囲は switch の {} に制限されている
	return i;
}

int hoge4(int v)
{
	switch(v){
	case 1: { //ダミーの {} をいれれば変数宣言は通るが
		int i = 0;
		}break;
	label: 
		i = 2; //error, 上の {} の外では i は 無効
		break;
	}
	//error, この i も無効
	return i;
}
int hoge5(int v)
{
	switch(v){
	int i = 0; //ラベルをいれなかったらこの変数宣言は有効
	case 1:
		i = 2;
		break;
	label:
		i += 3; //この場合, i の宣言だけが有効で代入(i=0)は無効
		//case の前か後かは関係ないようだ
		//コンパイラが未初期化の値を利用していると警告した
		break;
	}
	if(i < 4){ //error, i の有効期間は {} の中まで
		goto label;
	}
	return i;
}