Demi tujuan debugging, bisakah saya mendapatkan nomor baris di kompiler C / C ++? (cara standar atau cara khusus untuk kompiler tertentu)
misalnya
if(!Logical)
printf("Not logical value at line number %d \n",LineNumber);
// How to get LineNumber without writing it by my hand?(dynamic compilation)
Jawaban:
Anda harus menggunakan makro preprocessor
__LINE__
dan__FILE__
. Mereka adalah makro yang telah ditentukan sebelumnya dan bagian dari standar C / C ++. Selama preprocessing, mereka diganti masing-masing dengan string konstan yang memegang integer yang mewakili nomor baris saat ini dan dengan nama file saat ini.Variabel preprocessor lainnya:
__func__
: nama fungsi (ini adalah bagian dari C99 , tidak semua kompiler C ++ mendukungnya)__DATE__
: string dengan format "Mmm dd yyyy"__TIME__
: string dalam bentuk "hh: mm: ss"Kode Anda akan menjadi:
sumber
#define S1(N) #N
#define S2(N) S1(N)
#define LINESTR S2(__LINE__)
. Lihat c-faq.com/ansi/stringize.html__func__
ini bukan makro, ini adalah variabel yang dideklarasikan secara implisit.Sebagai bagian dari standar C ++, terdapat beberapa makro yang telah ditentukan sebelumnya yang dapat Anda gunakan. Bagian 16.8 dari standar C ++ mendefinisikan antara lain
__LINE__
makro.Jadi kode Anda adalah:
sumber
Anda bisa menggunakan makro dengan perilaku yang sama seperti printf () , kecuali makro juga menyertakan informasi debug seperti nama fungsi, kelas, dan nomor baris:
Makro ini harus berperilaku identik dengan printf () , sementara menyertakan informasi mirip java stacktrace. Berikut contoh mainnya:
Yang menghasilkan keluaran sebagai berikut:
sumber
#include
to<stdio.h>
Gunakan
__LINE__
(itu garis bawah ganda LINE garis bawah ganda), preprocessor akan menggantinya dengan nomor baris yang ditemukan.sumber
Checkout
__FILE__
dan__LINE__
makrosumber
C ++ 20 menawarkan cara baru untuk melakukannya dengan menggunakan std :: source_location . Ini saat ini dapat diakses di gcc dan clang as
std::experimental::source_location
with#include <experimental/source_location>
.Masalah dengan makro seperti itu
__LINE__
adalah jika Anda ingin membuat, misalnya fungsi logging yang mengeluarkan nomor baris saat ini bersama dengan pesan, Anda harus selalu meneruskan__LINE__
sebagai argumen fungsi, karena itu diperluas di situs panggilan. Sesuatu seperti ini:Akan selalu menampilkan baris deklarasi fungsi dan bukan baris tempat
log
sebenarnya dipanggil. Di sisi lain, denganstd::source_location
Anda dapat menulis sesuatu seperti ini:Di sini,
loc
diinisialisasi dengan nomor baris yang menunjuk ke lokasi tempatlog
dipanggil. Anda dapat mencobanya secara online di sini.sumber
Coba
__FILE__
dan__LINE__
.Anda mungkin juga menemukan
__DATE__
dan__TIME__
berguna.Meskipun kecuali Anda harus men-debug program di sisi klien dan dengan demikian perlu mencatat informasi ini, Anda harus menggunakan debugging normal.
sumber
raw code
(seperti ini: `__`). @mmyers berusaha membantu, tetapi dia hanya lolos dari salah satu garis bawah, dan karenanya Anda ditinggalkan dengan sintaks markup untuk cetak miring . Suara negatif agak keras di sini, saya setuju.Bagi mereka yang mungkin membutuhkannya, makro "FILE_LINE" untuk dengan mudah mencetak file dan baris:
sumber
Karena saya juga menghadapi masalah ini sekarang dan saya tidak dapat menambahkan jawaban untuk pertanyaan berbeda tetapi juga valid yang ditanyakan di sini , saya akan memberikan contoh solusi untuk masalah: hanya mendapatkan nomor baris tempat fungsi tersebut dipanggil C ++ menggunakan template.
Latar belakang: di C ++ seseorang dapat menggunakan nilai integer bukan tipe sebagai argumen template. Ini berbeda dari penggunaan tipikal tipe data sebagai argumen templat. Jadi idenya adalah menggunakan nilai integer tersebut untuk pemanggilan fungsi.
Keluaran:
Satu hal yang perlu disebutkan di sini adalah bahwa dalam C ++ 11 Standard dimungkinkan untuk memberikan nilai template default untuk fungsi yang menggunakan template. Dalam pra C ++ 11 nilai default untuk argumen non-tipe tampaknya hanya berfungsi untuk argumen template kelas. Jadi, di C ++ 11, tidak perlu memiliki definisi fungsi duplikat seperti di atas. Di C ++ 11 juga valid untuk memiliki argumen template char * const tetapi tidak memungkinkan untuk menggunakannya dengan literal seperti
__FILE__
atau__func__
seperti yang disebutkan di sini .Jadi pada akhirnya jika Anda menggunakan C ++ atau C ++ 11, ini mungkin alternatif yang sangat menarik daripada menggunakan makro untuk mendapatkan jalur panggilan.
sumber
Gunakan
__LINE__
, tapi apa tipenya?Sebagai konstanta integer , kode sering kali dapat mengasumsikan nilainya adalah
__LINE__ <= INT_MAX
dan jenisnya adalahint
.Untuk cetak di C,
printf()
membutuhkan specifier yang cocok:"%d"
. Ini adalah perhatian yang jauh lebih kecil di C ++ dengancout
.Pedantic concern: Jika nomor baris melebihi
INT_MAX
1 (bisa dibayangkan dengan 16-bitint
), mudah-mudahan kompilator akan menghasilkan peringatan. Contoh:Alternatifnya, kode dapat memaksa tipe yang lebih luas untuk mencegah peringatan tersebut.
Menghindari
printf()
Untuk menghindari semua batasan integer: stringify . Kode dapat langsung dicetak tanpa
printf()
panggilan: hal yang baik untuk dihindari dalam penanganan kesalahan 2 .1 Tentu saja praktik pemrograman yang buruk untuk memiliki file sebesar itu, namun mungkin kode yang dihasilkan mesin dapat menjadi tinggi.
2 Dalam debugging, terkadang kode tidak berfungsi seperti yang diharapkan. Memanggil fungsi kompleks seperti
*printf()
itu sendiri bisa menimbulkan masalah vs. sederhanafputs()
.sumber