Inisialisasi - apakah itu? Pra-pemulaan parameter fungsi

Bergantung pada cara program berkelakuan atau sepatutnya berkelakuan, anda boleh menyelesaikan masalah dengan cara yang berbeza. Seperti yang saya faham, Login_Form menerima/mengisi data tentang pengguna, kemudian di tempat di mana anda perlu mendapatkan user_id daripada borang ini, anda hanya menunggu sehingga tahap apabila borang telah menerima semua data dan kemudian anda menerima ID ini , ada baiknya, dengan cara ini, untuk merasmikan resit dalam bentuk kaedah GetUserId(), maka dalam kaedah ini anda boleh menunggu jeda sehingga data tiba dan hanya kemudian mengembalikan ID yang diperlukan. Jika tidak boleh menunggu serta-merta, maka anda perlu bool GetUserId(int & user_id) untuk kembali, contohnya, benar/salah jika sudah ada data atau tidak, dan hanya jika ia kembali benar maka user_id boleh dianggap diisi dengan nilai yang diperlukan. Itu. anda perlu menyimpan borang di suatu tempat dan kadangkala menanyakannya untuk mendapatkan data yang anda perlukan daripadanya, dan anda boleh sama ada membuat GetUserId() yang menyekat yang menunggu input atau yang tidak menyekat yang akan mengembalikan bendera kejayaan. Dalam kes ini, adalah penting bahawa sehingga semua data diterima di suatu tempat, borang ini disimpan sebagai pembolehubah atau ahli kelas. Penyelesaian anda apabila menyimpan penunjuk ke user_id adalah tidak selamat, siapa tahu sama ada objek borang itu hidup atau tidak lagi hidup, i.e. penunjuk mungkin sah atau mungkin tidak. Tetapi jika objek bentuk disimpan sepanjang masa sehingga ia dilaksanakan tindakan yang perlu maka ada jaminan bahawa semua kaedahnya akan berfungsi.

Sekiranya anda masih perlu menyelesaikan masalah ini dengan penunjuk, maka ini juga boleh diselesaikan, tidak seperti dalam kod anda, tetapi seperti ini - anda perlu menggunakan penunjuk pintar, contohnya std::shared_ptr, i.e. dalam kelas borang kita tidak menyimpan dua ahli (int user_id dan int * ptr_user_id), tetapi menyimpan satu ahli std::shared_ptr ptr_user_id, dalam pembina kita memperuntukkan memori untuknya ptr_user_id = new int(0), kemudian apabila perlu dalam borang yang kami isi pada masa yang sama Kami juga akan membolehkan untuk mendapatkannya daripada borang melalui shared_ptr GetUserIdPtr() const ( return ptr_user_id; ) . Di semua tempat di mana anda perlu menggunakan ID ini, salin sahaja ke my_copy_user_id ahli kelas kongsi_ptr anda; ... selepas membuat borang, kami melakukan my_copy_user_id = form.GetUserId() dan kini dalam borang kami dan dalam semua pengguna, kami semua mempunyai shared_ptr yang menunjuk ke satu ingatan bersama, sebagai hasilnya, anda kemudian boleh mendapatkan nilai penunjuk pada bila-bila masa, walaupun apabila objek borang dimusnahkan, semasa ia selamat, anda juga boleh sentiasa menyemak sama ada user_id telah diisi dengan nilai atau belum. , jika 0 bermakna ia belum diisi, jika tidak ia telah diisi. shared_ptr ialah kelas templat C++ standard yang mengira rujukan kepada memori kongsi bagi jenis tertentu dan membebaskannya apabila perlu, i.e. tiada apa yang perlu dilakukan untuk membebaskannya, dan pengiraan rujukan memastikan bahawa memori dibebaskan hanya apabila borang dan semua penggunanya ditamatkan. Juga, apabila borang telah dimusnahkan, penunjuk tetap sah kerana ingatan untuknya tidak dimusnahkan.

Senarai parameter dalam definisi dan prototaip fungsi, di samping memadankan jenis parameter, mempunyai satu lagi tujuan.

Pengisytiharan parameter mungkin mengandungi pemula, iaitu ungkapan yang mesti memberikan nilai awal untuk parameter. Pemula parameter bukan ungkapan tetap. Inisialisasi awal parameter tidak berlaku pada peringkat penyusunan (seperti, sebagai contoh, peruntukan memori untuk tatasusunan), tetapi secara langsung semasa pelaksanaan program.

Baris berikut menunjukkan contoh pengisytiharan fungsi dengan pemulaan parameter. Fungsi XX digunakan untuk memulakan parameter ww.

int ZZ(int tt, int ww = XX(BigVal));

Parameter kedua boleh dimulakan dengan cara ini, tanpa menyatakan namanya sama sekali. Sintaks pengisytiharan membolehkan anda melakukan ini!

int ZZ(int tt, int = XX(BigVal));

Satu-satunya syarat untuk permulaan sedemikian ialah jenis parameter sepadan dengan jenis ungkapan yang nilainya digunakan semasa permulaan permulaan.

Prototaip fungsi boleh ditempatkan dalam skop yang berbeza. Ia juga boleh diletakkan di dalam badan fungsi yang ditentukan. Setiap pengisytiharan fungsi boleh mengandungi pilihannya sendiri untuk mengisytiharkan dan memulakan parameter. Tetapi berbilang pengisytiharan fungsi yang sama dalam skop yang sama tidak membenarkan parameter dimulakan semula. Mesti ada had yang munasabah untuk segala-galanya.

Di samping itu, C++ mempunyai had lain yang berkaitan dengan susunan parameter dimulakan dalam skop. Permulaan dijalankan tanpa gagal dari parameter terakhir (paling kanan) dalam senarai pengisytiharan parameter. Permulaan parameter tidak membenarkan jurang: parameter yang dimulakan tidak boleh bergantian dengan parameter yang tidak dimulakan.

int MyF1 (int par1, int par2, int par3, int par4 = 10);

………………………………….

int MyF1 (int par1, int par2 = 20, int par3 = 20, int par4);

………………………………….

int MyF1(int par1 = 100, int, int, int);

#termasuk

int f(int, int=4);

int utama(int argc, char* argv)

printf("%d\n", f(2)); //8

printf("%d\n", f(2,3)); //6

int f(int a, int b)

Berfungsi dengan bilangan parameter yang berubah-ubah

Apabila memanggil fungsi dengan nombor pembolehubah parameter, sebarang bilangan argumen yang diperlukan ditentukan dalam panggilan ke fungsi ini. Dalam pengisytiharan dan definisi fungsi sedemikian nombor berubah-ubah argumen ditentukan oleh elipsis pada akhir senarai parameter formal atau senarai jenis argumen.

Semua hujah yang diberikan dalam panggilan fungsi ditolak ke timbunan. Bilangan parameter formal yang diisytiharkan untuk fungsi ditentukan oleh bilangan argumen yang diambil daripada timbunan dan diberikan kepada parameter formal. Pengaturcara bertanggungjawab untuk memilih argumen tambahan dengan betul dari tindanan dan menentukan bilangan argumen yang ada pada tindanan.

Contoh fungsi dengan bilangan parameter yang berubah-ubah ialah fungsi daripada perpustakaan fungsi bahasa SI yang melaksanakan operasi input/output maklumat (printf, scanf, dsb.). Fungsi printf() dalam perpustakaan diisytiharkan seperti berikut:

int printf(const char* ...);

Ini memastikan bahawa sebarang panggilan ke printf() akan diluluskan hujah pertama jenis const char*. Kandungan rentetan ini, dipanggil rentetan format, menentukan sama ada argumen tambahan diperlukan semasa membuat panggilan. Jika terdapat metakarakter dalam rentetan format yang bermula dengan simbol %, fungsi menunggu kehadiran argumen ini.

Pengaturcara boleh membangunkan fungsinya dengan bilangan parameter yang berubah-ubah. Untuk menyediakan cara yang mudah Untuk mengakses argumen fungsi dengan bilangan parameter yang berubah-ubah, terdapat tiga definisi makro (makro) va_start, va_arg, va_end, terletak dalam fail pengepala stdarg.h. Makro ini menunjukkan bahawa fungsi yang dibangunkan pengguna mempunyai beberapa argumen yang diperlukan diikuti dengan bilangan pembolehubah argumen pilihan. Argumen yang diperlukan boleh diakses melalui nama mereka, sama seperti semasa memanggil fungsi biasa. Untuk mendapatkan kembali argumen pilihan, gunakan makro va_start, va_arg, va_end dalam susunan berikut.

Makro va_start direka untuk menetapkan argumen arg_ptr ke permulaan senarai parameter pilihan dan kelihatan seperti fungsi dengan dua parameter:

void va_start(arg_ptr, prav_param);

Parameter prav_param mestilah parameter terakhir yang diperlukan bagi fungsi yang dipanggil, dan penunjuk arg_prt mesti diisytiharkan dengan pratakrif dalam senarai pembolehubah jenis va_list dalam bentuk:

va_list arg_ptr;

Makro va_start mesti digunakan sebelum penggunaan pertama makro va_arg.

Makro va_arg menyediakan akses kepada parameter semasa fungsi yang dipanggil dan juga kelihatan seperti fungsi dengan dua parameter

type_arg va_arg(arg_ptr,type);

Makro ini mendapatkan semula nilai jenis pada alamat yang ditentukan oleh penunjuk arg_ptr, menambah nilai penunjuk arg_ptr dengan panjang parameter yang digunakan (panjang jenis), dan dengan itu parameter arg_ptr akan menghala ke parameter seterusnya bagi fungsi yang dipanggil . Makro va_arg digunakan seberapa banyak yang diperlukan untuk mendapatkan semula semua parameter fungsi yang dipanggil.

Makro va_end digunakan selepas semua parameter fungsi telah diproses dan menetapkan penunjuk senarai parameter pilihan kepada sifar (NULL).

Mari kita pertimbangkan untuk menggunakan makro ini untuk memproses parameter fungsi yang mengira nilai purata bagi jujukan integer arbitrari. Oleh kerana fungsi mempunyai bilangan parameter yang berubah-ubah, kami akan menganggap nilai yang sama dengan -1 sebagai penghujung senarai. Oleh kerana senarai mesti mempunyai sekurang-kurangnya satu elemen, fungsi akan mempunyai satu parameter yang diperlukan.

#termasuk

#termasuk

int sred_znach(int,...);

n=sred_znach(2,3,4,-1); /* panggilan dengan empat parameter */

printf("n=%d\n",n);

n=sred_znach(5,6,7,8,9,-1); /* panggilan dengan enam parameter */

printf("n=%d\n",n);

int sred_znach(int x,...)

int i=0, j=0, jumlah=0;

va_start(uk_arg,x); /* tetapkan penunjuk uk_arg kepada */

/* parameter pilihan pertama */

jika (x!=-1) jumlah=x; /* semak jika senarai kosong */

else return (0);

manakala ((i=va_arg(uk_arg,int))!=-1)

/* memilih yang seterusnya */

( /* parameter dan semak */

jumlah+=i; /* hingga akhir senarai */

va_end(uk_arg); /* tutup senarai parameter */

Contoh 2: Pilihan lain mungkin - parameter pertama fungsi bertanggungjawab untuk bilangan elemen yang dijumlahkan. Di samping itu, anda boleh menolak untuk menggunakan makro dan menghuraikan timbunan dalam kod fungsi.

#termasuk

#termasuk

int sred_znach2(int,...);

n=sred_znach2(3,2,3,4);

printf("n=%d\n",n);

int sred_znach2(int n,...)

int *pPointer =

untuk (int i=n ; i; i--) Sum += *(++pPointer);

Inisialisasi

Pembolehubah dalam pengisytiharan boleh diberikan nilai awal melalui pemula. Entri pemula dalam pengisytiharan didahului dengan tanda sama

= <pemula>

Pembolehubah dari sebarang jenis boleh dimulakan. Fungsi tidak dimulakan. Pengisytiharan yang menggunakan spesifikasi kelas memori luaran, tidak boleh mengandungi pemula.

Pembolehubah yang diisytiharkan secara luaran tanpa spesifikasi kelas storan boleh dimulakan paling banyak sekali dalam mana-mana fail sumber yang membentuk atur cara. Jika ia tidak dimulakan secara eksplisit dalam mana-mana fail sumber, maka pemaut memulakannya kepada sifar.

Pembolehubah kelas memori statik, diisytiharkan pada kedua-dua peringkat luaran dan dalaman, boleh dimulakan dengan ungkapan malar tidak lebih daripada sekali setiap fail sumber. Jika ia tidak dimulakan secara eksplisit, pengkompil C memulakannya kepada sifar.

Memulakan Pembolehubah Kelas Memori auto Dan mendaftar dilaksanakan setiap kali anda memasuki blok (kecuali untuk memasukkan blok menggunakan operator pergi ke) di mana ia diisytiharkan. Jika pemula ditiadakan dalam perisytiharan pembolehubah kelas memori auto atau mendaftar, maka nilai awalnya tidak ditentukan. Permulaan pembolehubah jenis komposit (tatasusunan, struktur, kesatuan) yang mempunyai kelas memori auto, adalah dilarang dalam SP MSC, tetapi dibenarkan dalam SP TS walaupun untuk pembolehubah yang diisytiharkan dengan pengubah suai const. Pembolehubah jenis komposit mempunyai kelas ingatan statik, boleh dimulakan secara dalaman.

Nilai permulaan untuk pembolehubah tahap luaran dan pembolehubah kelas memori statik tahap dalaman mestilah ungkapan tetap (lihat bahagian 4.2.9). Pembolehubah Kelas Memori auto Dan mendaftar boleh dimulakan bukan sahaja dengan ungkapan malar, tetapi juga dengan ungkapan yang mengandungi pembolehubah dan panggilan fungsi.

Daripada buku C++ oleh Hill Murray

5.2.4 Permulaan Menggunakan fungsi seperti set_date() untuk memastikan pemulaan objek kelas adalah tidak elegan dan terdedah kepada ralat. Oleh kerana tiada mana-mana dinyatakan bahawa objek mesti dimulakan, pengaturcara mungkin terlupa untuk berbuat demikian, atau (yang

Dari buku Panduan Bantuan dalam C++ pengarang Stroustrap Bjarne

6.6 Tugasan dan Permulaan Pertimbangkan rentetan kelas rentetan yang sangat mudah: rentetan struct (* char* p; saiz int; // saiz vektor yang ditunjuk oleh pstring(int sz) (* p = new char; *) ~string() (* padam p; *) *); Rentetan ialah struktur data yang terdiri daripada vektor aksara dan panjang vektor ini. vektor

Daripada buku Idiom and Styles C++ oleh Makhmutov Albert

Daripada buku System Programming in Persekitaran Windows oleh Hart Johnson M

R.12.6 Permulaan Objek kelas tanpa pembina, tiada ahli peribadi atau dilindungi, tiada fungsi maya dan tanpa kelas asas boleh dimulakan menggunakan senarai pemula (§R.8.4.1). Objek kelas dengan pembina mesti dimulakan atau mempunyai

Daripada buku Infrastruktur kunci awam pengarang Polyanskaya Olga Yurievna

Daripada buku The C Programming Language for komputer peribadi pengarang Bochkov S. O.

Langkah 12 - Permulaan Dua Langkah. Apabila kami mencipta contoh bukan tindanan, kami menulis kod berikut: CClass* cc = new CClass(); Mari cuba fikirkan. new ialah pengendali global dengan definisi: void* operator new (size_t bytes); Ia menerima daripada pengkompil bilangan bait yang diperlukan untuk penyimpanan objek,

Daripada buku QNX/UNIX [Anatomy of Concurrency] pengarang Tsilurik Oleg Ivanovich

Inisialisasi API Winsock Winsock disokong DLL(WS2_32.DLL), untuk mendapatkan akses yang anda perlukan untuk menyambungkan perpustakaan WS_232.LIB ke program. DLL ini harus dimulakan menggunakan fungsi WSAStartup bukan standard, khusus Winsock, yang sepatutnya menjadi yang pertama

Daripada buku The C Language - A Guide for Beginners oleh Prata Steven

Permulaan Pada peringkat permulaan, bergantung pada parameter input Pembolehubah keadaan yang diperlukan untuk mengesahkan laluan pensijilan ditetapkan. DALAM keadaan pembolehubah Pelbagai kekangan dikekalkan yang diambil kira semasa mengesahkan laluan. Pembolehubah

Daripada buku Pengaturcaraan untuk Linux. Pendekatan profesional oleh Mitchell Mark

Permulaan Pembolehubah dalam pengisytiharan boleh diberikan nilai permulaan melalui pemula. Entri pemula dalam pengisytiharan didahului dengan tanda sama dengan =<инициализатор>Pembolehubah dari sebarang jenis boleh dimulakan. Fungsi tidak dimulakan.

Dari buku C++ untuk pemula oleh Lippman Stanley

Memulakan parameter int pthread_mutexattr_init(const pthread_mutexattr_t* attr); Fungsi ini memulakan struktur atribut mutex yang ditunjuk oleh parameter attr. Jenis data pthread_mutecasttr_t ditakrifkan dalam fail (berasal daripada jenis sync_attr_t, yang seterusnya ditakrifkan dalam fail

Dari buku pengarang

Inisialisasi Mutex int pthread_mutex_init(pthread_mutex_t* mutex, const pthread_mutexattr_t* attr); Struktur data pthread_mutex_t ditakrifkan dalam fail (jenis terbitan daripada jenis sync_t, yang seterusnya ditakrifkan dalam fail ) dan mempunyai bentuk berikut: struct _sync_t ( /* Kaunter untuk rekursif

Dari buku pengarang

Memulakan struktur Kita telah melihat bagaimana pembolehubah dan tatasusunan dimulakan: int count = 0;statik int fibo=(0, 1, 1, 2, 3, 5, 8); Adakah mungkin untuk memulakan pembolehubah struktur juga? Ya, jika pembolehubah struktur adalah luaran atau statik. Perlu diingat di sini bahawa

Dari buku pengarang

5.2.2. Memulakan Semaphore Peruntukan dan permulaan semaphore adalah dua operasi berbeza. Untuk memulakan semaphore, panggil fungsi semctl() , lulus hujah kedua sama dengan sifar, dan hujah ketiga adalah sama dengan pemalar SETALL. Hujah keempat mestilah jenis union semun, field

Dari buku pengarang

7.9.2. Permulaan dan penetapan Ingat bahawa nama tatasusunan tanpa menyatakan indeks elemen ditafsirkan sebagai alamat elemen pertama. Begitu juga, nama fungsi tanpa tanda kurungan ditafsirkan sebagai penunjuk fungsi. Contohnya, semasa mengira

Dari buku pengarang

14.1. Memulakan Kelas Pertimbangkan definisi kelas berikut: Data kelas (public:int ival;char *ptr;);Untuk menggunakan objek kelas dengan selamat, anda mesti memulakan ahlinya dengan betul. Walau bagaimanapun, maksud tindakan ini berbeza untuk kelas yang berbeza. Sebagai contoh, boleh ival

Dari buku pengarang

14.6. Permulaan Memberwise A Permulaan satu objek kelas oleh objek lain kelas yang sama, seperti: Account oldAcct(" Anna Livia Plurabelle");Account newAcct(oldAcct); dipanggil pengamulaan ahli lalai. Secara lalai - kerana ia dilakukan secara automatik, secara bebas

Program SI biasa ialah definisi fungsi utama, yang hendak dilaksanakan tindakan yang perlu memanggil fungsi lain. Contoh program di atas ialah fail sumber tunggal yang mengandungi semua fungsi yang diperlukan untuk menjalankan program. Komunikasi antara fungsi telah dijalankan berdasarkan data dengan menghantar parameter dan mengembalikan nilai fungsi. Tetapi pengkompil SI juga membolehkan anda memecahkan program kepada beberapa bahagian berasingan (fail sumber), menterjemah setiap bahagian secara berasingan, dan kemudian menggabungkan semua bahagian menjadi satu fail boleh laku menggunakan pemaut.

Dengan struktur sedemikian program asal fungsi yang terletak dalam fail sumber yang berbeza boleh menggunakan pembolehubah luaran global. Semua fungsi dalam bahasa C mengikut definisi luaran dan sentiasa boleh diakses dari mana-mana fail. Sebagai contoh, jika program terdiri daripada dua fail sumber, seperti yang ditunjukkan dalam Rajah 2, maka fungsi utama boleh memanggil mana-mana daripada tiga fungsi fun1, fun2, fun3, dan setiap satu daripada fungsi ini boleh memanggil mana-mana yang lain.

Untuk membolehkan fungsi yang ditetapkan untuk melaksanakan sebarang tindakan, ia mesti menggunakan pembolehubah. Dalam SI, semua pembolehubah mesti diisytiharkan sebelum ia boleh digunakan. Pengisytiharan memetakan nama dan atribut pembolehubah, fungsi atau jenis. Mentakrifkan pembolehubah menyebabkan memori diperuntukkan untuk menyimpan nilainya. Kelas memori yang diperuntukkan ditentukan oleh penentu kelas memori, dan mentakrifkan hayat dan skop pembolehubah yang dikaitkan dengan konsep blok program.

Dalam bahasa SI, blok ialah urutan pengisytiharan, takrifan dan pernyataan yang disertakan pendakap gigi. Terdapat dua jenis blok - penyataan kompaun dan definisi fungsi, yang terdiri daripada penyataan kompaun, yang merupakan badan fungsi, dan pengepala fungsi mendahului badan (yang merangkumi nama fungsi, jenis pulangan dan parameter formal ). Blok boleh termasuk pernyataan majmuk, tetapi bukan definisi fungsi. Blok dalam dipanggil bersarang, dan unit luaran- menyeluruh.

Sepanjang hayat ialah selang masa pelaksanaan program semasa objek program (pembolehubah atau fungsi) wujud. Jangka hayat pembolehubah boleh menjadi tempatan atau global. Pembolehubah dengan jangka hayat global mempunyai memori yang diperuntukkan kepadanya dan nilai khusus sepanjang pelaksanaan program, bermula dari saat pembolehubah diisytiharkan. Pembolehubah dengan jangka hayat setempat mempunyai memori yang diperuntukkan kepadanya dan nilai yang ditentukan hanya semasa pelaksanaan blok di mana pembolehubah ditakrifkan atau diisytiharkan. Setiap kali blok dimasukkan, pembolehubah tempatan diperuntukkan ingatan baru, yang dikeluarkan apabila keluar dari blok.

Semua fungsi dalam SI mempunyai seumur hidup global dan wujud sepanjang masa pelaksanaan program.

Skop ialah sebahagian daripada teks program di mana ia boleh digunakan objek ini. Objek dianggap kelihatan dalam blok atau fail sumber jika nama dan jenis objek dalam blok atau fail itu diketahui. Objek boleh kelihatan dalam blok, fail sumber atau merentas semua fail sumber yang membentuk atur cara. Ia bergantung pada tahap apa objek diisytiharkan: pada tahap dalaman, i.e. di dalam beberapa blok, atau di luar, i.e. di luar semua blok.

Jika objek diisytiharkan di dalam blok, maka ia boleh dilihat dalam blok ini dan dalam semua blok dalaman. Jika objek diisytiharkan pada tahap luaran, maka ia boleh dilihat dari titik pengisytiharannya hingga ke penghujung fail sumber yang diberikan.

Objek boleh dilihat secara global melalui pengisytiharan yang sesuai dalam semua fail sumber yang membentuk atur cara.

Penentu kelas memori dalam perisytiharan berubah boleh menjadi auto, daftar, statik atau luaran. Jika kelas memori tidak ditentukan, maka ia ditentukan secara lalai dari konteks pengisytiharan.

Objek kelas auto dan daftar mempunyai waktu tempatan kehidupan. Penentu statik dan luaran mentakrifkan objek dengan jangka hayat global.

Apabila mengisytiharkan pembolehubah pada peringkat dalaman, mana-mana daripada empat penentu kelas memori boleh digunakan, dan jika ia tidak dinyatakan, maka kelas memori automatik diandaikan.

Pembolehubah dengan auto kelas memori mempunyai jangka hayat setempat dan hanya boleh dilihat dalam blok di mana ia diisytiharkan. Memori untuk pembolehubah sedemikian diperuntukkan apabila memasuki blok dan dibebaskan apabila keluar dari blok. Apabila blok dimasukkan semula, bahagian memori lain mungkin diperuntukkan untuk pembolehubah ini.

Pembolehubah dengan auto kelas storan tidak dimulakan secara automatik. Ia mesti dimulakan secara eksplisit apabila diisytiharkan dengan memberikannya nilai awal. Pembolehubah yang tidak dimulakan dengan auto kelas storan dianggap tidak ditentukan.

Penentu kelas memori daftar mengarahkan pengkompil untuk memperuntukkan memori untuk pembolehubah dalam daftar jika boleh. Menggunakan memori daftar biasanya menyebabkan masa capaian berubah-ubah berkurangan. Pembolehubah yang diisytiharkan dengan kelas storan daftar mempunyai skop yang sama seperti pembolehubah auto. Bilangan daftar yang boleh digunakan untuk nilai pembolehubah dihadkan oleh keupayaan komputer, dan jika pengkompil tidak mempunyai daftar percuma di pelupusannya, maka pembolehubah diperuntukkan memori seperti untuk kelas auto. Kelas memori daftar hanya boleh ditentukan untuk pembolehubah dengan taip int atau penunjuk dengan saiz yang sama dengan saiz int.

Pembolehubah yang diisytiharkan secara dalaman dengan penentu kelas storan statik menyediakan keupayaan untuk menyimpan nilai pembolehubah apabila keluar dari blok dan menggunakannya apabila memasuki semula blok. Pembolehubah sedemikian mempunyai jangka hayat dan skop global dalam blok di mana ia diisytiharkan. Tidak seperti pembolehubah auto, yang diperuntukkan pada tindanan, pembolehubah statik diperuntukkan dalam segmen data dan oleh itu mengekalkan nilainya apabila blok itu keluar.

Contoh: /* mengisytiharkan pembolehubah i pada tahap dalaman dengan statik kelas memori. */ /* fail sumber fail1.c */ main() ( ... ) fun1() ( int statik i=0; ... ) /* fail sumber fail2.c */ fun2() ( int statik i= 0; ... ) fun3() ( int statik i=0; ... )

Dalam contoh di atas, tiga pembolehubah berbeza dengan statik kelas memori diisytiharkan dan mempunyai nama yang sama i. Setiap pembolehubah ini mempunyai jangka hayat global, tetapi hanya boleh dilihat dalam blok (fungsi) di mana ia diisytiharkan. Pembolehubah ini boleh digunakan untuk mengira bilangan panggilan kepada setiap tiga fungsi.

Pembolehubah kelas memori statik boleh dimulakan dengan ungkapan malar. Jika tiada permulaan yang jelas, maka pembolehubah sedemikian diberikan nilai sifar. Apabila memulakan dengan ungkapan alamat malar, anda boleh menggunakan alamat mana-mana objek luaran, kecuali untuk alamat objek dengan kelas memori auto, kerana alamat yang terakhir tidak tetap dan berubah dengan setiap kemasukan ke dalam blok. Permulaan dilakukan sekali pada kemasukan pertama ke dalam blok.

Pembolehubah yang diisytiharkan secara tempatan dengan extern kelas storan ialah rujukan kepada pembolehubah dengan nama yang sama ditakrifkan secara global dalam salah satu fail sumber program. Tujuan pengisytiharan sedemikian adalah untuk menjadikan definisi pembolehubah peringkat global kelihatan dalam blok.

Contoh: /* isytiharkan pembolehubah i, iaitu nama tatasusunan luaran bagi integer panjang, pada peringkat tempatan */ /* fail sumber fail1.c */ main() ( ... ) fun1() ( extern long i; ... ) /* fail sumber fail2.c */ panjang i=(0); seronok2() ( ... ) seronok3() ( ... )

Mengisytiharkan i sebagai extern dalam contoh di atas menjadikannya kelihatan di dalam fun1. Takrif pembolehubah ini adalah dalam file2.c pada peringkat global dan hanya perlu ada satu, manakala terdapat beberapa pengisytiharan dengan extern kelas memori.

Pengisytiharan dengan extern kelas memori diperlukan jika perlu untuk menggunakan pembolehubah yang diterangkan dalam fail sumber semasa, tetapi lebih rendah dalam teks program, i.e. sebelum definisi globalnya selesai. Contoh berikut menggambarkan penggunaan pembolehubah bernama st.

Contoh: main() ( extern int st; ... ) static int st=(0); seronok1() ( ... )

Mengisytiharkan pembolehubah dengan penentu luaran memberitahu pengkompil bahawa memori untuk pembolehubah tidak perlu diperuntukkan, kerana ini dilakukan di tempat lain dalam program.

Apabila mengisytiharkan pembolehubah di peringkat global, penentu kelas memori statik atau luaran boleh digunakan, dan anda juga boleh mengisytiharkan pembolehubah tanpa menentukan kelas memori. Kelas memori auto dan daftar tidak dibenarkan untuk pengisytiharan global.

Mengisytiharkan pembolehubah di peringkat global ialah sama ada definisi pembolehubah atau rujukan kepada definisi yang dibuat di tempat lain dalam program. Pengisytiharan pembolehubah global yang memulakan pembolehubah itu (sama ada secara eksplisit atau tersirat) ialah definisi pembolehubah. Takrifan di peringkat global boleh diberikan dalam bentuk berikut:

1. Pembolehubah diisytiharkan dengan statik kelas memori. Pembolehubah sedemikian boleh dimulakan dengan ungkapan pemalar eksplisit, atau dengan nilai lalai sifar. Iaitu, pengisytiharan static int i=0 dan static int i adalah setara, dan dalam kedua-dua kes pembolehubah i akan diberikan nilai 0.

2. Pembolehubah diisytiharkan tanpa menentukan kelas memori, tetapi dengan permulaan yang jelas. Pembolehubah ini diberikan kelas memori statik secara lalai. Iaitu, pengisytiharan int i=1 dan int statik i=1 akan menjadi setara.

Pembolehubah yang diisytiharkan secara global boleh dilihat dalam baki fail sumber yang ditakrifkan. Di atas penerangannya dan dalam fail sumber lain, pembolehubah ini tidak kelihatan (melainkan ia diisytiharkan dengan kelas luar).

Pembolehubah global hanya boleh ditakrifkan sekali dalam skopnya. Dalam fail sumber lain, pembolehubah global lain dengan nama yang sama dan dengan statik kelas memori boleh diisytiharkan, tidak akan ada konflik, kerana setiap pembolehubah ini akan kelihatan hanya dalam fail sumbernya.

Penentu kelas memori luaran untuk pembolehubah global digunakan, seperti untuk pengisytiharan tempatan, sebagai rujukan kepada pembolehubah yang diisytiharkan di tempat lain dalam program, i.e. untuk meluaskan skop pembolehubah. Dengan pengisytiharan sedemikian, skop pembolehubah dilanjutkan ke penghujung fail sumber di mana pengisytiharan dibuat.

Pengisytiharan dengan extern kelas storan tidak membenarkan pemulaan kerana pengisytiharan ini merujuk kepada pembolehubah yang sedia ada dan yang ditakrifkan sebelumnya.

1.6.2. Pengisytiharan Fungsi

Fungsi sentiasa ditakrifkan secara global. Mereka boleh diisytiharkan dengan kelas memori statik atau luaran. Pengisytiharan fungsi di peringkat tempatan dan global mempunyai maksud yang sama.

Peraturan untuk menentukan skop fungsi berbeza daripada peraturan keterlihatan untuk pembolehubah dan adalah seperti berikut.

1. Fungsi yang diisytiharkan sebagai statik boleh dilihat dalam fail yang ditakrifkan. Setiap fungsi boleh memanggil fungsi lain dengan statik kelas storan daripada fail sumbernya, tetapi tidak boleh memanggil fungsi yang ditakrifkan dengan statik kelas storan dalam fail sumber lain. Pelbagai fungsi dengan kelas memori statik yang mempunyai nama yang sama boleh ditakrifkan dalam fail sumber yang berbeza tanpa menyebabkan konflik.

2. Fungsi yang diisytiharkan dengan kelas memori luaran boleh dilihat dalam semua fail sumber program. Sebarang fungsi boleh memanggil fungsi dengan kelas memori luaran.

3. Jika tiada penentu kelas memori dalam pengisytiharan fungsi, maka kelas luaran diandaikan secara lalai.

Pengkompil meletakkan semua objek dengan extern kelas memori dalam jadual khas dalam fail objek pautan luaran, yang digunakan oleh editor pautan untuk menyelesaikan pautan luaran. Sesetengah pautan luaran dijana oleh pengkompil semasa memanggil fungsi perpustakaan SI, jadi untuk menyelesaikan pautan ini, perpustakaan fungsi yang sepadan mesti tersedia kepada editor pautan.

1.6.3. Sepanjang hayat dan skop objek perisian

Jangka hayat pembolehubah (global atau tempatan) ditentukan mengikut peraturan berikut.

1. Pembolehubah yang diisytiharkan secara global (iaitu, di luar semua blok) wujud sepanjang keseluruhan pelaksanaan program.

2. Pembolehubah tempatan (iaitu diisytiharkan di dalam blok) dengan daftar atau kelas memori auto mempunyai seumur hidup hanya untuk tempoh pelaksanaan blok di mana ia diisytiharkan. Jika pembolehubah tempatan diisytiharkan dengan kelas memori statik atau luaran, maka ia mempunyai seumur hidup untuk tempoh keseluruhan program.

Keterlihatan pembolehubah dan fungsi dalam atur cara ditentukan oleh peraturan berikut.

1. Pembolehubah yang diisytiharkan atau ditakrifkan secara global boleh dilihat dari titik pengisytiharan atau definisi hingga ke penghujung fail sumber. Anda boleh membuat pembolehubah kelihatan dalam fail sumber lain dengan mengisytiharkannya dengan kelas memori luaran dalam fail ini.

2. Pembolehubah yang diisytiharkan atau ditakrifkan secara tempatan boleh dilihat dari titik pengisytiharan atau takrifan ke penghujung blok semasa. Pembolehubah sedemikian dipanggil tempatan.

3. Pembolehubah daripada blok yang disertakan, termasuk pembolehubah yang diisytiharkan di peringkat global, boleh dilihat dalam blok dalam. Keterlihatan ini dipanggil bersarang. Jika pembolehubah yang diisytiharkan di dalam blok mempunyai nama yang sama seperti pembolehubah yang diisytiharkan dalam blok penutup, maka pembolehubah tersebut adalah pembolehubah yang berbeza, dan pembolehubah dari blok penutup dalam blok dalam akan tidak kelihatan.

4. Fungsi dengan statik kelas memori hanya boleh dilihat dalam fail sumber di mana ia ditakrifkan. Semua fungsi lain boleh dilihat sepanjang program.

Label dalam fungsi boleh dilihat sepanjang keseluruhan fungsi.

Nama parameter formal yang diisytiharkan dalam senarai parameter prototaip fungsi hanya boleh dilihat dari titik pengisytiharan parameter hingga penghujung pengisytiharan fungsi.

1.6.4. Memulakan pembolehubah global dan tempatan

Apabila memulakan, anda mesti mematuhi peraturan berikut:

1. Pengisytiharan yang mengandungi penentu kelas memori luaran tidak boleh mengandungi pemula.

2. Pembolehubah global sentiasa dimulakan, dan melainkan ini dilakukan secara eksplisit, ia dimulakan kepada sifar.

3. Pembolehubah dengan statik kelas memori boleh dimulakan dengan ungkapan malar. Inisialisasi untuk mereka dilakukan sekali sebelum permulaan program. Jika tiada pemulaan eksplisit, maka pembolehubah dimulakan kepada sifar.

4. Permulaan pembolehubah dengan auto kelas memori atau daftar dilakukan setiap kali anda memasuki blok di mana ia diisytiharkan. Jika pembolehubah tidak dimulakan dalam pengisytiharan, maka nilai awalnya tidak ditentukan.

5. Nilai awal untuk pembolehubah global dan untuk pembolehubah dengan kelas memori statik mestilah ungkapan malar. Alamat pembolehubah tersebut ialah pemalar, dan pemalar ini boleh digunakan untuk memulakan penunjuk yang diisytiharkan secara global. Alamat pembolehubah dengan auto kelas memori atau daftar bukan pemalar dan tidak boleh digunakan dalam pemula.

Contoh: int global_var; int func(void) ( int local_var; /* default auto */ static int *local_ptr=&local_var; /* ini salah */ static int *global_ptr=&global_var; /* ini betul */ daftar int *reg_ptr=&local_var; /* dan begitu betul */ )

Dalam contoh di atas, pembolehubah global global_var mempunyai jangka hayat global dan Alamat tetap dalam ingatan, dan alamat ini boleh digunakan untuk memulakan penunjuk statik global_ptr. Pembolehubah tempatan local_var, yang mempunyai kelas memori auto, diperuntukkan dalam memori sahaja semasa fungsi func sedang berjalan; alamat pembolehubah ini bukan pemalar dan tidak boleh digunakan untuk memulakan pembolehubah statik local_ptr. Untuk memulakan pembolehubah daftar tempatan reg_ptr, anda boleh menggunakan ungkapan bukan pemalar, dan, khususnya, alamat pembolehubah local_ptr.

[

Klasifikasi penunjuk fungsi

Definisi penunjuk fungsi

Penunjuk fungsi

Biasanya parameter fungsi digunakan untuk menyediakan antara muka data antara konteks titik panggilan dan konteks fungsi. Penggunaan penunjuk fungsi membolehkan kami memperkenalkan jenis baru parameter. Parameter fungsi yang berkaitan dengan jenis baharu ini membolehkan anda menghantar fungsi lain ke dalam fungsi yang anda sedang bangunkan. Akibatnya, ia menjadi mungkin untuk meningkatkan tahap kesejagatan fungsi yang dibangunkan.

Penunjuk fungsi ialah sama ada ungkapan yang nilainya ialah alamat fungsi, atau pembolehubah yang menyimpan alamat fungsi. Alamat fungsi selalunya alamat permulaannya. kod program. Walau bagaimanapun, pada sesetengah penyusun, alamat fungsi mungkin alamat objek yang mengandungi alamat permulaan kod atur cara fungsi.

Terdapat dua jenis penunjuk fungsi dalam C:

· penunjuk – ungkapan,

· pembolehubah penunjuk.

38.9.3. Penunjuk - ungkapan

Seperti yang dinyatakan di atas, ungkapan penunjuk ialah ungkapan yang nilainya ialah alamat fungsi. Mari kita beri contoh.

Biarkan terdapat prototaip fungsi untuk mengira kuasa dua bilangan dua jenis. Kemudian ungkapan &sqr ialah ungkapan penunjuk. Di sini & ialah operator alamat unary, yang mengarahkan pengkompil untuk mengira alamat fungsi.

38.9.4. Penunjuk - pembolehubah

Pembolehubah penunjuk ialah pembolehubah yang direka untuk menyimpan alamat fungsi. Mari kita pertimbangkan format untuk menentukan pembolehubah sedemikian.

(* <α>) (<γ>)

· * - pengendali dereference,

α – pengecam penunjuk yang diisytiharkan,

· b - jenis nilai yang dikembalikan oleh fungsi yang penuding boleh ditetapkan.

· γ – senarai jenis parameter fungsi yang penuding boleh ditetapkan.

Mari kita berikan contoh mengisytiharkan pembolehubah-penunjuk.

double (*pf)(double);

Ini adalah pengisytiharan berubah-ubah. Nama pembolehubah pf. nilai pembolehubah ini boleh menjadi alamat mana-mana fungsi yang mengambil satu parameter jenis berganda dan yang mengembalikan nilai jenis berganda.

Memandangkan perkara di atas, kita boleh mengatakan bahawa takrif penunjuk fungsi menentukan set fungsi yang boleh digunakan. Pembolehubah penunjuk pf yang diisytiharkan di atas boleh berfungsi dengan, sebagai contoh, fungsi berikut.

dua persegi (dua kali x)
{

kubus dua kali ganda (ganda x)
{

pulangkan x * x * x;

Mari kita kembali kepada pengisytiharan penunjuk - pembolehubah pf. Mari kita pertimbangkan tujuan kurungan digunakan di dalamnya. Terdapat dua pasang di sini.



double (*pf)(double);

Pasangan kedua kurungan ialah operator fungsi. Timbul persoalan: "Apakah peranan yang dimainkan oleh pasangan kurungan pertama?" Untuk memahami isu ini, mari kita alih keluar pasangan kurungan ini buat sementara waktu. Kemudian ungkapan yang dimaksudkan akan mengambil bentuk berikut.

double *pf(double);

Ungkapan yang terhasil ialah pengisytiharan fungsi yang mengambil satu parameter jenis double dan mengembalikan penunjuk jenis double*. Untuk memastikan ini, mari kita ingat bahawa sintaks pengisytiharan dalam bahasa C mengandungi sintaks ungkapan. Untuk menentukan tujuan nama pf dalam ungkapan yang dimaksudkan, pertimbangkan subungkapan *pf(double). Di sini dua pengendali digunakan pada nama pf: * dan () . Tafsiran nama pf bergantung pada keutamaan pengendali ini. Jika anda melihat jadual keutamaan operator, anda boleh melihat bahawa operator fungsi () mempunyai keutamaan yang lebih tinggi daripada operator dereference *. Ia berikutan bahawa pengendali () mengikat nama pf dengan lebih kuat daripada operator *. Jadi, dalam edisi baharu, pf ialah nama fungsi, bukan nama penunjuk.

Sekarang mari kita kembali kepada iklan asal.

double (*pf)(double);

Tanda kurung pertama dalam ungkapan ini menggabungkan susunan pengelompokan operator dan operan. Sekarang nama pf menjadi nama penunjuk.

Penunjuk – Pembolehubah boleh dimulakan pada masa pengisytiharannya sama ada ke penunjuk nol atau ke alamat fungsi jenis yang penuding boleh ditetapkan.

Biarkan terdapat dua fungsi yang mempunyai prototaip berikut.

petak dua (double x);
kubus berganda(x berganda);

Mari kita isytiharkan tiga penunjuk fungsi:

ganda (*pf1)(ganda) =
double (*pf2)(double)= kubus;

dua kali ganda (*pf3)(ganda)= 0;

Sintaks dengan mana dua pembolehubah pertama (pf1 dan pf2) diisytiharkan adalah sedikit berbeza. Sintaks yang dengannya pembolehubah pertama (pf1) diisytiharkan adalah tidak diragui tentang ketepatannya. Di sebelah kanan tanda tugasan ialah ungkapan yang nilainya ialah alamat fungsi. Mungkin terdapat keraguan tentang ketepatan pengisytiharan kedua, di mana pembolehubah pf2 diisytiharkan. Pengisytiharan ini menggunakan nama fungsi dan bukannya alamatnya sebagai pemula. Walau bagaimanapun, kod ini disusun dengan baik. Hakikatnya ialah bahasa C sentiasa dalam kod di mana penunjuk kepada fungsi dijangka, dan nama fungsi ditemui, secara automatik menukar nama fungsi menjadi penunjuk.

Komen. Operasi pemulaan juga dilakukan apabila menggunakan eksponen fungsi sebagai parameter formal fungsi.