To znany błąd w gcc.
gcc ma documented extension który umożliwia zestawienie postaci
goto *ptr;
gdzie ptr
może być dowolne wyrażenie typu void*
. W ramach tego rozszerzenia podanie jednoargumentowej nazwy &&
na nazwę etykiety powoduje podanie adresu etykiety typu: void*
.
W przykładzie:
int foo = 0;
goto *foo;
foo
wyraźnie jest typu int
, nie typu void*
. Wartość int
można przekonwertować na void*
, ale tylko w przypadku jawnego rzutowania (z wyjątkiem specjalnego przypadku zerowej stałej wskaźnika, która nie ma tu zastosowania).
Samo wyrażenie *foo
jest prawidłowo diagnozowane jako błąd. I tak:
goto *42;
kompiluje bez błędów (wygenerowany kod maszyna wydaje się być skok zająć 42
, jeśli mam poprawnie czyta kod montaż).
Szybkie eksperyment wskazuje, że gcc generuje ten sam kod montażowy
goto *42;
jak dla
goto *(void*)42;
Ten ostatni jest prawidłowe stosowanie udokumentowanego rozszerzenia, i to, co powinieneś prawdopodobnie, jeśli z jakiegoś powodu chcesz przeskoczyć pod adres 42.
Zgłosiłem bug report - który został szybko zamknięty jako duplikat this bug report, przesłane w 2007.
To znany błąd. Zobacz moją zaktualizowaną odpowiedź. –