Mengapa #ifndef dan #define digunakan dalam file header C ++?

496

Saya telah melihat kode seperti ini biasanya di awal file header:

#ifndef HEADERFILE_H
#define HEADERFILE_H

Dan pada akhir file tersebut

#endif

Apa tujuan dari ini?

Asad Khan
sumber
36
+1 - Saya juga memiliki keraguan yang sama, dan mendapat jawaban yang jauh lebih baik di sini, semoga bermanfaat bagi pengunjung masa depan: stackoverflow.com/q/3246803/1134940
Abid Rahman K
6
Saya ingin menambahkan ini bahwa Anda juga dapat menggunakan #pragma sekali , itu yang harus Anda lakukan dan melayani tujuan yang sama seperti ifndef. Untuk perbandingan keduanya, lihat: stackoverflow.com/questions/1143936/…
Dimensi
3
Lebih baik menyebutkan apa #pragmaitu: mengaktifkan fitur khusus-kompiler. Meskipun #pragma onceini sangat didukung secara luas, itu tidak standar.
Potatoswatter
3
@ Dimensi: Dokumentasi GNU sendiri ( info cppatau lihat di sini ) mengatakan "itu tidak dikenali oleh semua preprosesor, jadi Anda tidak dapat mengandalkannya dalam program portabel.". Dan GNU cpp mengoptimalkan #ifndefidiom umum dan portabel sehingga seefisien itu #pragma once.
Keith Thompson
3
Beberapa hal yang perlu dipertimbangkan: Jangan gunakan nama makro yang dimulai dengan garis bawah; pengidentifikasi tersebut dicadangkan untuk implementasi. Lebih halus, #ifndef HEADERFILE_Hdapat melanggar namespace implementasi dari nama header terjadi untuk memulai E; pengidentifikasi dimulai dengan Edan digit atau huruf besar disediakan untuk <errno.h>. Saya sarankan #ifndef H_HEADERFILE.
Keith Thompson

Jawaban:

527

Itu disebut penjaga #include .

Setelah tajuk dimasukkan, ia memeriksa apakah ada nilai unik (dalam hal ini HEADERFILE_H ) ditentukan. Kemudian jika itu tidak didefinisikan, ia mendefinisikannya dan berlanjut ke sisa halaman.

Ketika kode dimasukkan lagi, yang pertama ifndefgagal, menghasilkan file kosong.

Itu mencegah deklarasi ganda pengidentifikasi apa pun seperti tipe, enum dan variabel statis.

LiraNuna
sumber
1
Koning Baard XIV: VC bahkan memiliki #pragma onceyang melakukan hal yang sama :-)
Joey
95
Juga mencegah inklusi rekursif ... Bayangkan "alice.h" termasuk "bob.h" dan "bob.h" termasuk "alice.h" dan mereka tidak memiliki penjaga termasuk ...
Kevin Dungs
@ Kevin: itulah yang saya maksud. Saya ingin memanipulasi formulir yang dibuka oleh formulir untuk memanipulasi. Itu punya banyak kesalahan dan saya tidak tahu harus berbuat apa. Saya menyerah =)
6
Ј е е #pragma onceis : tidak portabel; #ifndefidiom umum direkomendasikan.
Keith Thompson
2
@CIsForCookies Punch "satu aturan definisi" ke dalam mesin pencari favorit Anda.
David Schwartz
33
#ifndef <token>
/* code */
#else
/* code to include if the token is defined */
#endif

#ifndefmemeriksa apakah token yang diberikan #definedlebih awal dalam file atau dalam file yang disertakan; jika tidak, itu termasuk kode antara itu dan penutupan #elseatau, jika tidak #elseada, #endifpernyataan. #ifndefsering digunakan untuk membuat file header idempoten dengan mendefinisikan token setelah file dimasukkan dan memeriksa bahwa token tidak diatur di bagian atas file itu.

#ifndef _INCL_GUARD
#define _INCL_GUARD
#endif
Roy
sumber
4
Pengidentifikasi dimulai dengan garis bawah dicadangkan; Anda tidak harus mendefinisikannya sendiri. Gunakan sesuatu seperti #ifndef H_HEADER_NAME.
Keith Thompson
5
Saya tahu ini adalah komentar lama, tetapi sebenarnya pembatasan garis bawah hanya berlaku untuk "pengidentifikasi eksternal" - pengidentifikasi yang dapat berakhir pada tabel simbol objek yang dikompilasi, yaitu variabel global dan nama fungsi. Itu tidak berlaku untuk nama makro.
Stu
1
Apakah komentar Stu benar? Saya baru saja membaca stackoverflow.com/questions/228783/… dan sekarang saya tidak begitu yakin.
Will
10

Ini mencegah dari dimasukkannya banyak file header yang sama beberapa kali.

#ifndef __COMMON_H__
#define __COMMON_H__
//header file content
#endif

Misalkan Anda telah memasukkan file header ini dalam beberapa file. Jadi pertama kali __COMMON_H__ tidak didefinisikan, itu akan didefinisikan dan menyertakan file header.

Lain kali __COMMON_H__ didefinisikan, jadi tidak akan disertakan lagi.

Sandeep_black
sumber
1

Mereka disebut ifdef atau termasuk penjaga.

Jika menulis sebuah program kecil, sepertinya itu tidak diperlukan, tetapi ketika proyek bertambah, Anda dapat dengan sengaja atau tidak sengaja memasukkan satu file berkali-kali, yang dapat menghasilkan kompilasi peringatan seperti variabel yang sudah dideklarasikan.

#ifndef checks whether HEADERFILE_H is not declared.
#define will declare HEADERFILE_H once #ifndef generates true.
#endif is to know the scope of #ifndef i.e end of #ifndef

Jika tidak dinyatakan yang berarti #ifndef menghasilkan true maka hanya bagian antara #ifndef dan #endif dieksekusi jika tidak. Ini akan mencegah dari lagi menyatakan pengidentifikasi, enum, struktur, dll ...

Mohit Jain
sumber