Terdapat banyak kontroversi tentang pernyataan goto dalam bahasa C, dan banyak buku mengesyorkan "gunakannya dengan berhati-hati atau elakkan menggunakannya." Walau bagaimanapun, dalam amalan Linus, bapa Linux, beliau secara meluas menggunakan pernyataan goto dalam Linux, yang juga memberi inspirasi kepada kami untuk menggunakan ciri ini secara munasabah.
Disebabkan kontroversi itu, kita perlu belajar menggunakan kenyataan goto. Mari lihat beberapa sintaks asas dan contoh pernyataan goto:
1. Sintaks asas goto
Pernyataan goto terdiri daripada dua bahagian: kata kunci goto dan nama tag. Peraturan penamaan untuk label adalah sama dengan peraturan untuk pembolehubah. Contoh:
goto label;
Untuk penyataan ini berfungsi dengan betul, fungsi itu juga mesti mengandungi label berlabel pernyataan lain, yang bermula dengan nama label diikuti dengan titik bertindih, seperti:
label:printf("goto here.n");
Leret ke kiri dan kanan untuk melihat semua kod>>>>
/* 编译环境:mingw32 gcc6.3.0 */ #include #include /* goto测试 */ void TestGoto(void) { int i; while (1) { for (i = 0; i if (i > 6) { goto label; } printf("%s : i = %d\n", __FUNCTION__, i); } } label: printf("test goto end!"); } int main(void) { TestGoto(); }
Hasil lari:
Daripada hasil yang sedang dijalankan, kita jelas dapat mengetahui penggunaan goto, yang boleh melompat keluar daripada berbilang gelung Apabila pernyataan goto ditemui semasa pelaksanaan program, ia boleh melompat ke label untuk meneruskan pelaksanaan.
Satu perkara yang perlu diberi perhatian ialah: pernyataan goto dan label lompatannya mestilah dalam fungsi yang sama.
Ia juga merupakan pernyataan lompat. Apakah perbezaan antara pernyataan goto dan penyataan break dan continue?
Sebenarnya, break dan continue adalah bentuk khas goto. Kelebihan menggunakan break dan continue ialah nama mereka sudah menunjukkan penggunaannya.
Mari kita lihat penggunaan rehat dan teruskan melalui contoh kod:
Gunakan program ujian di atas untuk membina fungsi void TestBreak(void);
untuk menguji pernyataan rehat, seperti:
Leret ke kiri atau kanan untuk melihat semua kod>>>>
/* break测试 */ void TestBreak(void) { int i; while (1) { for (i = 0; i if (i > 6) { break; /* 第一个break:跳出for循环 */ } printf("%s : i = %d\n", __FUNCTION__, i); } printf("Now i = %d\n", i); break; /* 第一个break:跳出while循环 */ } printf("test break end!"); }
Hasil lari:
Daripada keputusan larian, kita boleh tahu dengan jelas bahawa rehat boleh keluar dari gelung semasa.
Dalam contoh ini, pernyataan putus pertama keluar dari gelung arus untuk, dan pernyataan putus kedua keluar dari gelung semasa semasa. Ia boleh dilihat bahawa rehat boleh keluar dari gelung.
Jadi, mengikut ciri-ciri break dan goto, jika anda ingin melompat keluar dari banyak peringkat gelung, ia akan menjadi lebih mudah untuk menggunakan goto.
Begitu juga, bina fungsi void TestContinue(void);
untuk menguji pernyataan continue, seperti:
Leret ke kiri dan kanan untuk melihat semua kod>>>>
/* continue测试 */ void TestContinue(void) { int i; for (i = 0; i if (i > 6) { printf("i = %d, continue next loop\n", i); continue; /* continue:结束本次循环(而不是终止这一层循环)继续进入下一次循环 */ } printf("%s : i = %d\n", __FUNCTION__, i); } printf("test break end!"); }
Hasil lari:
Kita boleh tahu dengan jelas daripada hasil larian yang berterusan boleh menamatkan gelung ini (bukan keseluruhan gelung) dan masukkan gelung seterusnya (i mewakili bilangan gelung).
不提倡使用goto的占比应该比较多,不提倡的原因主要是:很容易把逻辑弄乱且难以理解。
这一部分人认为goto可以用在以下两种情况比较方便:
这个例子就类似于我们上面的goto测试程序。
一个函数的执行过程可能会产生很多种情况异常情况。下面有几种处理方式,以代码为例:
方法一:做出判断后,如果条件出错,直接return。
*左右滑动查看全部代码>>>*
int mystrlen(char *str) { int count = 0; if (str == NULL) { return-1; } if (*str == 0) { return0; } while(*str != 0 ) { count++; str++; } return count; }
方法二:先设置一个变量,对变量赋值,只有一个return。
*左右滑动查看全部代码>>>*
int mystrlen(char *str) { int ret; if (str == NULL) { ret = -1; } elseif (*str == 0) { ret = 0; } else { ret = 0; while(*str != 0 ) { ret++; str++; } } return ret; }
方法三:使用goto语句。
*左右滑动查看全部代码>>>*
int mystrlen(char *str) { int ret; if (str == NULL) { ret = -1; goto _RET; } if (*str == 0) { ret = 0; goto _RET; } while(*str !=0 ) { ret++; str++; } _RET: return ret; }
其中,方法三就是很多人都提倡的方式。统一用goto err跳转是最方便且效率最高的,从反汇编语句条数可以看出指令用的最少,消耗的寄存器也最少,效率无疑是最高的。
并且,使用goto可以使程序变得更加可扩展。当程序需要在错误处理时释放资源时,统一到goto处理最方便。这也是为什么很多大型项目,开源项目,包括Linux,都会大量的出现goto来处理错误!
Atas ialah kandungan terperinci Mengapakah goto digunakan secara meluas dalam kernel Linux, tetapi banyak buku tidak menyokong penggunaannya?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!