زبان C دستور goto را در اختیار برنامهنویس قرار میدهد — دستوری که میشود گفت بهصورت بینهایت قابل سوءاستفاده است.
این دستور به همراه «برچسبها» (labels) به شما اجازه میدهد به نقطهای خاص از برنامه بپرید.
بهصورت رسمی، دستور goto هیچوقت لازم نیست؛
و در عمل هم تقریباً همیشه میتوان بدون آن، کد تمیزتر و قابلفهمتری نوشت.
در این کتاب ما اصلاً از goto استفاده نکردهایم.
با این حال، در تعداد کمی از موقعیتها، ممکن است goto مفید باشد.
یکی از رایجترین موارد، زمانی است که میخواهید از یک ساختار تو در تو (مثلاً چند حلقهی پشت سر هم) بهطور ناگهانی خارج شوید — چیزی که با break نمیشود انجام داد، چون break فقط از درونیترین حلقه خارج میشود.
مثلاً:
for ( ... )
for ( ... ) {
...
if (disaster)
goto error;
}
...
error:
/* clean up the mess */
این ساختار زمانی مفید است که کد مربوط به مدیریت خطا (error handling) ساده نباشد
و ممکن است خطاها در چند جای مختلف رخ دهند.
یک برچسب (label) درست مثل یک نام متغیر نوشته میشود و بعد از آن یک «دونقطه» میآید.
هر برچسب را میتوان جلوی هر دستور در همان تابعی که goto در آن است، قرار داد.
حوزهی اعتبار یک برچسب، کل تابع است.
بهعنوان مثال دیگر، فرض کنید میخواهیم بررسی کنیم آیا دو آرایهی a و b حداقل یک عنصر مشترک دارند یا نه.
میتوانیم بنویسیم:
for (i = 0; i < n; i++)
for (j = 0; j < m; j++)
if (a[i] == b[j])
goto found;
/* didn't find any common element */
...
found:
/* got one: a[i] == b[j] */
...
کدی که از goto استفاده میکند همیشه میتواند بدون آن هم نوشته شود —
هرچند شاید لازم شود چند شرط تکراری اضافه کنیم یا از یک متغیر کمکی استفاده کنیم.
مثلاً همین جستجوی آرایه را میشود اینطور نوشت:
found = 0;
for (i = 0; i < n && !found; i++)
for (j = 0; j < m && !found; j++)
if (a[i] == b[j])
found = 1;
if (found)
/* got one: a[i-1] == b[j-1] */
...
else
/* didn't find any common element */
...
بهجز چند استثنا مثل همین موارد، کدی که به goto وابسته است
معمولاً سختتر فهمیده میشود و نگهداریاش هم دشوارتر است.
ما در این مورد تعصب نداریم، اما به نظر میرسد استفاده از goto باید خیلی کم، یا حتی هیچوقت انجام شود.