Pengenalan

Pengenalan

Kami telah sampai ke titik penting dalam siri artikel kami mengenai perkembangan C. Ia juga, bukan secara kebetulan, bahagian C yang memberikan banyak sakit kepala kepada pemula. Di sinilah kita masuk, dan tujuan artikel ini (salah satu daripada mereka), adalah untuk membongkar mitos tentang petunjuk dan tentang C sebagai bahasa yang sukar/mustahil untuk belajar dan membaca. Walau bagaimanapun, kami mengesyorkan perhatian yang lebih tinggi dan sedikit kesabaran dan anda akan melihat bahawa petunjuk tidak seperti mind-boggling seperti kata legenda.

Definisi dan amaran

Nampaknya wajar dan masuk akal bahawa kita harus bermula dengan amaran, dan kami dengan sungguh -sungguh mengesyorkan anda mengingati mereka: sementara petunjuk menjadikan hidup anda sebagai pemaju c lebih mudah, mereka juga boleh memperkenalkan pepijat yang sukar dicari dan kod yang tidak dapat difahami. Anda akan melihat, jika anda terus membaca, apa yang kita bicarakan dan keseriusan pepijat tersebut, tetapi garis bawah adalah, seperti yang dikatakan sebelum ini, berhati -hati.

Takrif mudah penunjuk akan menjadi "pembolehubah yang nilainya adalah alamat pembolehubah lain". Anda mungkin tahu bahawa sistem operasi berurusan dengan alamat semasa menyimpan nilai, sama seperti anda akan melabelkan perkara di dalam gudang sehingga anda mempunyai cara mudah untuk mencari mereka apabila diperlukan. Sebaliknya, array boleh ditakrifkan sebagai koleksi item yang dikenal pasti oleh indeks. Anda akan melihat kemudian mengapa petunjuk dan tatasusunan biasanya dibentangkan bersama, dan bagaimana untuk menjadi efisien dalam c menggunakannya. Sekiranya anda mempunyai latar belakang bahasa yang lain, lebih tinggi, anda sudah biasa dengan datatype rentetan. Di C, tatasusunan adalah bersamaan dengan pembolehubah bertenaga rentetan, dan dikatakan bahawa pendekatan ini lebih efisien.



Petunjuk

Anda telah melihat definisi penunjuk, sekarang mari kita mulakan dengan beberapa penjelasan yang mendalam dan, tentu saja, contohnya. Soalan pertama yang mungkin anda tanyakan kepada diri sendiri adalah "Mengapa saya harus menggunakan petunjuk?". Walaupun saya mungkin mendapat bising perbandingan ini, saya akan mengambil peluang saya: adakah anda menggunakan symlinks dalam sistem linux anda? Walaupun anda belum mencipta diri anda, sistem anda memanfaatkannya dan ia menjadikan kerja lebih cekap. Saya telah mendengar beberapa cerita seram tentang pemaju senior C yang bersumpah mereka tidak pernah menggunakan petunjuk kerana mereka "rumit", tetapi itu hanya bermakna pemaju tidak cekap, tidak lebih. Selain itu, terdapat situasi di mana anda perlu menggunakan petunjuk, jadi mereka tidak boleh dianggap sebagai pilihan, kerana mereka tidak. Seperti dahulu, saya percaya untuk belajar dengan contoh, jadi di sini pergi:

int x, y, z; x = 1; y = 2; int *ptoi; /* ptoi adalah, dan bermaksud, penunjuk ke integer*/ ptoi = & x; / * ptoi menunjuk ke x */ z = *ptoi; / * z sekarang 1, nilai x, ke arah mana ptoi menunjukkan */ ptoi = & y; / *ptoi kini menunjuk ke y */

Sekiranya anda menggaru kepala anda dalam kekeliruan, jangan lari: ia hanya menyakitkan buat kali pertama, anda tahu. Mari kita line mengikut baris dan lihat apa yang kita buat di sini. Kami mula -mula mengisytiharkan tiga bilangan bulat, iaitu x, y dan z, dan memberikan nilai x dan y 1 dan 2,. Ini adalah bahagian yang mudah. Elemen baru disertakan dengan perisytiharan PTOI yang berubah -ubah, iaitu penunjuk kepada integer, jadi ia Mata ke arah integer. Ini dicapai dengan menggunakan asterisk sebelum nama pemboleh ubah dan dikatakan sebagai pengendali redirect. Garis 'ptoi = & x;' bermaksud "PTOI kini menunjuk ke arah X, yang mesti menjadi integer, seperti perisytiharan PTOI di atas". Anda kini boleh bekerjasama dengan PTOI seperti yang anda lakukan dengan x (baik, hampir). Mengetahui ini, baris seterusnya adalah bersamaan dengan 'z = x;'. Seterusnya, kami dereference ptoi, yang bermaksud kita mengatakan "berhenti menunjuk ke x dan mula menunjuk ke y". Satu pemerhatian penting diperlukan di sini: pengendali hanya boleh digunakan pada objek pemasangan memori, yang menjadi pembolehubah (kecuali daftar [1]) dan array elemen.

[1] Pembolehubah jenis daftar adalah salah satu elemen C yang wujud, tetapi majoriti pengaturcara mengelakkan mereka. Pemboleh ubah dengan kata kunci ini dilampirkan mencadangkan kepada pengkompil bahawa ia akan digunakan sering dan ia harus disimpan dalam daftar pemproses untuk akses yang lebih cepat. Pengkompil yang paling moden mengabaikan petunjuk ini dan memutuskan untuk diri mereka sendiri, jadi jika anda tidak pasti anda perlu mendaftar, anda tidak.

Kami mengatakan bahawa ptoi mesti menunjuk kepada integer. Bagaimana kita harus meneruskan jika kita mahukan penunjuk generik, jadi kita tidak perlu bimbang tentang jenis data? Masukkan penunjuk untuk tidak sah. Ini semua yang akan kami ceritakan kepada anda, dan tugasan pertama adalah untuk mengetahui apa yang digunakan oleh penunjuk yang boleh dibatalkan dan apakah batasannya.



Tatasusunan

Anda akan melihat dalam sub-bab ini mengapa kami menegaskan untuk menyampaikan petunjuk dan tatasusunan dalam satu artikel, walaupun risiko melampaui otak pembaca. Senang mengetahui bahawa, ketika bekerja dengan tatasusunan, anda tidak perlu menggunakan petunjuk, tetapi senang melakukannya, kerana operasi akan lebih cepat, dengan kelemahan kod yang kurang difahami. Perisytiharan array mempunyai hasil mengisytiharkan beberapa elemen berturut -turut yang tersedia melalui indeks, seperti itu:

int a [5]; int x; A [2] = 2; x = a [2];

A adalah array 5-elemen, dengan elemen ketiga ialah 2 (penomboran indeks bermula dengan sifar!), dan x ditakrifkan sebagai juga 2. Banyak pepijat dan kesilapan ketika pertama kali berurusan dengan array adalah bahawa seseorang melupakan masalah 0-indeks. Apabila kita berkata "unsur -unsur berturut -turut" kita bermaksud bahawa ia dijamin bahawa unsur -unsur array mempunyai lokasi berturut -turut dalam ingatan, bukan jika [2] adalah 2, maka [3] adalah 3. Terdapat struktur data di C yang disebut enum yang melakukannya, tetapi kita tidak akan berurusan dengannya. Saya menjumpai beberapa program lama yang saya tulis semasa belajar C, dengan bantuan dari rakan saya Google, yang membalikkan watak -watak dalam rentetan. Ini dia:

#include #include int main () char stringy [30]; int i; char c; printf ("Taipkan rentetan .\ n "); fgets (stringy, 30, stdin); printf (" \ n "); untuk(i = 0; i < strlen(stringy); i++) printf("%c", stringy[i]); printf("\n"); untuk(i = strlen (stringy); i> = 0; i--) printf ("%c", stringy [i]); printf ("\ n"); kembali 0;  

Ini adalah salah satu cara untuk melakukan ini tanpa menggunakan petunjuk. Ia mempunyai kelemahan dalam banyak aspek, tetapi ia menggambarkan hubungan antara rentetan dan tatasusunan. Stringy adalah array 30 aksara yang akan digunakan untuk memegang input pengguna, saya akan menjadi indeks array dan c akan menjadi watak individu yang akan diusahakan. Oleh itu, kami meminta rentetan, kami menyimpannya ke array menggunakan fgets, mencetak rentetan asal dengan bermula dari tali [0] dan meneruskan, menggunakan gelung secara berperingkat, sehingga rentetan berakhir. Operasi terbalik memberikan hasil yang diingini: kami sekali lagi mendapatkan panjang rentetan dengan strlen () dan mulakan undur 'til sifar kemudian cetak watak rentet. Satu lagi aspek penting ialah sebarang array watak di C berakhir dengan watak null, yang diwakili secara grafik oleh '\ 0'.

Bagaimana kita akan melakukan semua ini menggunakan petunjuk? Jangan tergoda untuk menggantikan array dengan penunjuk ke char, yang tidak akan berfungsi. Sebaliknya, gunakan alat yang sesuai untuk pekerjaan. Untuk program interaktif seperti yang ada di atas, gunakan tatasusunan aksara panjang tetap, digabungkan dengan fungsi selamat seperti fgets (), jadi anda tidak akan digigit oleh limpahan penampan. Walau bagaimanapun, untuk pemalar rentetan, anda boleh menggunakan

char * myName = "David";

Dan kemudian, menggunakan fungsi yang diberikan kepada anda dalam rentetan.H, memanipulasi data seperti yang anda lihat sesuai. Bercakap di mana, fungsi apa yang akan anda pilih untuk menambah nama myname ke rentetan yang menangani pengguna? Sebagai contoh, bukannya "sila masukkan nombor" anda harus mempunyai "David, sila masukkan nombor".



Petunjuk dan tatasusunan

Anda boleh, dan digalakkan, menggunakan tatasusunan bersempena dengan petunjuk, walaupun pada mulanya anda mungkin terkejut kerana sintaks. Secara umumnya, anda boleh melakukan apa sahaja yang berkaitan dengan penunjuk, dengan kelebihan kelajuan di sisi anda. Anda mungkin berfikir bahawa dengan perkakasan hari ini, menggunakan petunjuk dengan tatasusunan hanya untuk mendapatkan kelajuan tidak berbaloi. Walau bagaimanapun, apabila program anda berkembang dalam saiz dan kerumitan, perbezaan akan mula menjadi lebih jelas, dan jika anda pernah memikirkan untuk memindahkan permohonan anda ke beberapa platform tertanam, anda akan mengucapkan tahniah. Sebenarnya, jika anda memahami apa yang dikatakan sehingga ke tahap ini, anda tidak akan mempunyai alasan untuk terkejut. Katakan kami mempunyai pelbagai bilangan bulat dan kami ingin mengisytiharkan penunjuk ke salah satu elemen array. Kod akan kelihatan seperti ini:

int myarray [10]; int *myptr; int x; myptr = & myArray [0]; x = *myptr;

Oleh itu, kami mempunyai array bernama MyArray, yang terdiri daripada sepuluh bilangan bulat, penunjuk kepada integer, yang mendapat alamat elemen pertama array, dan x, yang mendapat nilai unsur pertama yang dikatakan melalui penunjuk. Sekarang anda boleh melakukan pelbagai helah bagus untuk bergerak melalui array, seperti

*(myptr + 1);

yang akan menunjuk ke arah elemen MyArray seterusnya, iaitu MyArray [1].

Satu perkara penting untuk diketahui, dan pada masa yang sama satu yang menggambarkan dengan sempurna hubungan antara penunjuk dan tatasusunan, adalah bahawa nilai objek jenis array adalah alamat elemen 'pertama (sifar), jadi jika myptr = & myArray [ 0], maka myptr = myArray. Sebagai latihan, kami menjemput anda untuk mengkaji hubungan ini sedikit dan kod beberapa situasi di mana anda fikir ia akan/boleh berguna. Inilah yang akan anda hadapi sebagai aritmetik penunjuk.

Pertimbangan mengenai rentetan dalam C dan panggilan

Sebelum kita melihat bahawa anda boleh melakukan sama ada

char *mystring; mystring = "Ini adalah rentetan."

atau anda boleh melakukan perkara yang sama dengan menggunakan

char mystring [] = "Ini adalah rentetan.";

Dalam kes kedua, seperti yang anda mungkin telah disimpulkan, mystring adalah array yang cukup besar untuk memegang data yang dikaitkan dengannya. Perbezaannya ialah dengan menggunakan array, anda boleh beroperasi pada aksara individu di dalam rentetan, sementara dengan menggunakan pendekatan penunjuk anda tidak dapat. Ini adalah isu yang sangat penting untuk diingat yang akan menyelamatkan anda dari pengkompil yang mempunyai lelaki besar yang datang ke rumah anda dan melakukan perkara -perkara yang mengerikan kepada nenek anda. Melangkah lebih jauh, isu lain yang harus anda ketahui ialah jika anda melupakan petunjuk, panggilan di C dibuat mengikut nilai. Oleh itu, apabila fungsi memerlukan sesuatu dari pemboleh ubah, salinan tempatan dibuat dan kerja dilakukan pada itu. Tetapi jika fungsi itu mengubah pemboleh ubah, perubahan tidak dicerminkan, kerana asal tetap utuh. Dengan menggunakan petunjuk, anda boleh menggunakan panggilan dengan rujukan, Seperti yang anda lihat dalam contoh kami di bawah. Juga, panggilan dengan nilai mungkin menjadi intensif sumber jika objek yang sedang dijalankan adalah besar. Secara teknikal, ada juga panggilan oleh penunjuk, tetapi mari kita tetap mudah buat masa ini.

Katakan kita mahu menulis fungsi yang mengambil integer sebagai hujah dan meningkatkannya dengan nilai. Anda mungkin akan tergoda untuk menulis sesuatu seperti ini:

void inc (int a) a+= 20; 

Sekarang jika anda mencuba ini, anda akan melihat bahawa integer tidak akan ditingkatkan, kerana hanya salinan tempatan. Sekiranya anda akan menulis

void inc (int & a) a+= 20; 

Hujah integer anda akan ditingkatkan dengan dua puluh, yang anda mahukan. Oleh itu, jika anda masih mempunyai keraguan tentang kegunaan petunjuk, inilah satu contoh yang mudah namun penting.



Topik yang agak maju

Kami berfikir tentang meletakkan topik ini di bahagian khas kerana mereka agak sukar untuk difahami untuk pemula, tetapi berguna, mesti mengetahui bahagian pengaturcaraan C. Jadi…

Petunjuk kepada petunjuk

Ya, petunjuk adalah pembolehubah seperti yang lain, jadi mereka boleh menunjuk kepada mereka. Walaupun petunjuk mudah seperti yang dilihat di atas mempunyai satu tahap "menunjuk", petunjuk kepada penunjuk mempunyai dua, jadi titik pembolehubah seperti yang lain yang menunjuk kepada yang lain. Anda fikir ini memang marah? Anda boleh mempunyai petunjuk kepada petunjuk kepada petunjuk kepada petunjuk ke… .iklan infinitum, tetapi anda sudah menyeberangi ambang kewarasan dan kegunaan jika anda mendapat pengisytiharan sedemikian. Kami mengesyorkan menggunakan CDECL, yang merupakan program kecil yang biasanya tersedia di kebanyakan distro Linux yang "diterjemahkan" antara C dan C ++ dan Bahasa Inggeris dan sebaliknya. Oleh itu, penunjuk kepada penunjuk boleh diisytiharkan sebagai

int ** ptrtoptr;

Sekarang, seperti bagaimana penunjuk pelbagai peringkat digunakan, ada situasi apabila anda mempunyai fungsi, seperti perbandingan di atas, dan anda ingin mendapatkan penunjuk dari mereka sebagai nilai pulangan. Anda juga mungkin mahukan pelbagai rentetan, yang merupakan ciri yang sangat berguna, seperti yang anda lihat dengan keinginan.

Susunan pelbagai dimensi

Array yang anda lihat setakat ini adalah unidimensional, tetapi itu tidak bermakna anda terhad kepada itu. Contohnya, array bi-dimensi dapat dibayangkan dalam fikiran anda sebagai pelbagai tatasusunan. Nasihat saya adalah untuk menggunakan susunan pelbagai dimensi jika anda merasakan keperluan, tetapi jika anda baik dengan yang mudah, baik 'unidimensional satu, gunakan itu supaya hidup anda sebagai pengkod akan lebih mudah. Untuk mengisytiharkan array dua dimensi (kami menggunakan dua dimensi di sini, tetapi anda tidak terhad kepada nombor itu), anda akan lakukan

 int BidimArray [4] [2];

yang akan memberi kesan mengisytiharkan array integer 4-by-2. Untuk mengakses elemen kedua secara menegak (fikirkan teka -teki silang kata jika membantu!) dan yang pertama mendatar, anda boleh lakukan

BidimArray [2] [1];

Ingat bahawa dimensi ini adalah untuk mata kita sahaja: pengkompil memperuntukkan memori dan berfungsi dengan array dengan cara yang sama, jadi jika anda tidak melihat utiliti ini, jangan gunakannya. Ergo, array kami di atas boleh diisytiharkan sebagai

int BidimArray [8]; / * 4 oleh 2, seperti yang dikatakan */


Argumen baris arahan

Dalam ansuran sebelumnya kami siri kami bercakap tentang Main dan bagaimana ia boleh digunakan dengan atau tanpa argumen. Apabila program anda memerlukannya dan anda mempunyai argumen, mereka adalah char argc dan char *argv []. Sekarang anda tahu apa array dan petunjuk, perkara -perkara mula masuk akal. Walau bagaimanapun, kami berfikir untuk mendapatkan sedikit terperinci di sini. char *argv [] boleh ditulis sebagai char ** argv juga. Seperti makanan untuk difikirkan, mengapa anda berfikir bahawa itu mungkin? Harap. Selalu anda boleh bergantung pada fakta bahawa argv [0] adalah nama program itu sendiri, sementara argv [1] adalah hujah pertama dan sebagainya. Jadi program pendek untuk melihat nama 'dan hujah -hujahnya akan kelihatan seperti ini:

#include #include int main (int argc, char ** argv)  manakala(argc--) printf ("%s \ n", *argv ++); kembali 0; 

Kesimpulan

Kami memilih bahagian -bahagian yang paling penting untuk pemahaman tentang petunjuk dan tatasusunan, dan sengaja meninggalkan beberapa subjek seperti petunjuk ke fungsi. Walau bagaimanapun, jika anda bekerja dengan maklumat yang dibentangkan di sini dan menyelesaikan latihan, anda akan mempunyai permulaan yang cukup baik pada bahagian C yang dianggap sebagai sumber utama kod rumit dan tidak dapat difahami.

Berikut adalah rujukan yang sangat baik mengenai penunjuk C ++. Walaupun ia bukan C, bahasa berkaitan, jadi artikel itu akan membantu anda lebih memahami petunjuk.

Inilah yang boleh anda harapkan seterusnya:

  • I. C Pembangunan di Linux - Pengenalan
  • Ii. Perbandingan antara c dan bahasa pengaturcaraan lain
  • Iii. Jenis, pengendali, pembolehubah
  • Iv. Kawalan aliran
  • V. Fungsi
  • Vi. Petunjuk dan tatasusunan
  • VII. Struktur
  • Viii. Asas I/O
  • Ix. Gaya dan cadangan pengekodan
  • X. Membina program
  • Xi. Pembungkusan untuk Debian dan Fedora
  • Xii. Mendapatkan pakej di repositori debian rasmi

Tutorial Linux Berkaitan:

  • Pengenalan kepada Automasi, Alat dan Teknik Linux
  • Perkara yang hendak dipasang di Ubuntu 20.04
  • Menguasai Gelung Skrip Bash
  • Gelung bersarang dalam skrip bash
  • Mint 20: Lebih baik daripada Ubuntu dan Microsoft Windows?
  • Manipulasi data besar untuk keseronokan dan keuntungan bahagian 1
  • Perkara yang perlu dilakukan setelah memasang ubuntu 20.04 Focal Fossa Linux
  • Tutorial Debugging GDB untuk Pemula
  • Pembalakan Lanjutan dan Pengauditan di Linux
  • Berapa kerap anda perlu reboot pelayan Linux anda?