Unconditional jumps are used extensively in C, "break" and "continue" are both unconditional jumps - "goto" is simply an unconditional jump to a label.
goto's implemented over short distances to clear labels are justified when you need to balance speed, minimisation of stack use and minimisation of code size.
The most useful situation I have seen goto's used is in the context of a device driver, when a sequence of resources need to be secured prior to an operation being performed. In the event of an error associated with the allocation of one of the resources, the resources already allocated need to be released in the opposite order to their allocation (it's good practice to do this to avoid deadlock). goto offers a concise solution to this operational paradigm:
get resource A
if (error)
goto out_a;
get resource B
if (error)
goto out_b;
get resource C
if (error)
goto out_c;
perform actions;
goto out;
out_c:
undo C
out_b:
undo B:
out_a:
undo A
out:
return ret;
The alternative, using nested if's, looks worse and requires a lot of extra work if you add another resource to allocate, or if you use functions then you use up limited stack space (unless you inline, and then you get code bloat)
Frankly, if you can follow program flow which uses break or continue (which don't have labels), you should be able to follow program flow which uses goto sparingly and clearly. If you can't, then you have no business touching someone else's device driver code.
Overall, I think that the education strategy of goto avoidance is worthwhile, but at some point you ought to become proficient enough to be trusted with all of a language's features, judiciously applied.