Apakah ada cara untuk menentukan argumen default ke fungsi di C?
c
arguments
default-parameters
Nathaniel Flath
sumber
sumber
Jawaban:
Tidak juga. Satu-satunya cara adalah dengan menulis fungsi varargs dan secara manual mengisi nilai default untuk argumen yang tidak dilewati pemanggil.
sumber
open(2)
system call menggunakan ini untuk argumen opsional yang mungkin ada, tergantung pada argumen yang diperlukan, danprintf(3)
membaca string format yang menetapkan berapa argumen akan ada. Keduanya menggunakan vararg dengan cukup aman dan efektif, dan meskipun Anda pasti dapat mengacaukannya,printf()
terutama tampaknya cukup populer.Wow, semua orang pesimis di sini. Jawabannya iya.
Ini bukan hal sepele: pada akhirnya, kita akan memiliki fungsi inti, struct pendukung, fungsi wrapper, dan makro di sekitar fungsi wrapper. Dalam pekerjaan saya, saya memiliki satu set makro untuk mengotomatisasi semua ini; setelah Anda memahami alurnya, akan mudah bagi Anda untuk melakukan hal yang sama.
Saya telah menulis ini di tempat lain, jadi di sini ada tautan eksternal terperinci untuk melengkapi ringkasan di sini: http://modelingwithdata.org/arch/00000022.htm
Kami ingin berbelok
menjadi fungsi yang menggunakan default (i = 8, x = 3.14). Tentukan struct pengiring:
Ganti nama fungsi Anda
f_base
, dan tentukan fungsi pembungkus yang menetapkan default dan memanggil basis:Sekarang tambahkan makro, menggunakan makro variadic C. Dengan cara ini pengguna tidak perlu tahu mereka sebenarnya sedang mengisi a
f_args
struct dan berpikir mereka melakukan hal yang biasa:Oke, sekarang semua hal berikut ini akan berfungsi:
Periksa aturan tentang bagaimana initializers majemuk menetapkan default untuk aturan yang tepat.
Satu hal yang tidak akan berhasil:
f(0)
karena kami tidak dapat membedakan antara nilai yang hilang dan nol. Dalam pengalaman saya, ini adalah sesuatu yang harus diwaspadai, tetapi dapat diatasi ketika kebutuhan muncul --- separuh waktu default Anda benar-benar nol.Saya mengalami kesulitan menulis ini karena saya pikir argumen bernama dan default benar-benar membuat pengkodean dalam C lebih mudah dan bahkan lebih menyenangkan. Dan C luar biasa karena begitu sederhana dan masih memiliki cukup di sana untuk memungkinkan semua ini.
sumber
{}
(penginisialisasi kosong) adalah kesalahan C99.#define vrange(...) CALL(range,(param){.from=1, .to=100, .step=1, __VA_ARGS__})
Iya. :-) Tapi tidak dengan cara yang Anda harapkan.
Sayangnya, C tidak memungkinkan Anda untuk membebani metode sehingga Anda akan memiliki dua fungsi yang berbeda. Namun, dengan memanggil f2, Anda sebenarnya akan memanggil f1 dengan nilai default. Ini adalah solusi "Don't Repeat Yourself", yang membantu Anda menghindari menyalin / menempel kode yang ada.
sumber
Kita dapat membuat fungsi yang menggunakan parameter bernama (hanya) untuk nilai default. Ini adalah kelanjutan dari jawaban bk.
Standar C99 mendefinisikan bahwa nama-nama yang belakangan dalam inisialisasi menimpa item sebelumnya. Kami juga dapat memiliki beberapa parameter posisi standar, cukup ubah tanda tangan makro dan fungsinya. Parameter nilai default hanya dapat digunakan dalam gaya parameter bernama.
Output program:
sumber
OpenCV menggunakan sesuatu seperti:
Jika pengguna tidak tahu apa yang harus ia tulis, trik ini dapat membantu:
sumber
Tidak.
Bahkan standar C99 terbaru tidak mendukung hal ini.
sumber
Tidak, itu fitur bahasa C ++.
sumber
Jawaban singkat: Tidak.
Jawaban yang sedikit lebih lama: Ada solusi lama, lama tempat Anda meneruskan string yang Anda uraikan untuk argumen opsional:
di mana opt dapat menyertakan pasangan "name = value" atau sesuatu, dan yang Anda inginkan
Jelas ini hanya berguna sesekali. Umumnya ketika Anda ingin antarmuka tunggal ke keluarga fungsi.
Anda masih menemukan pendekatan ini dalam kode fisika partikel yang ditulis oleh program profesional dalam c ++ (seperti misalnya ROOT ). Keuntungan utamanya adalah dapat diperpanjang hampir tanpa batas dengan tetap mempertahankan kompatibilitas.
sumber
struct
dan membuat penelepon membuat, mengisi kolom untuk opsi yang berbeda, dan kemudian meneruskannya dengan alamat, atau meneruskanNULL
untuk opsi default.Mungkin cara terbaik untuk melakukan ini (yang mungkin atau mungkin tidak mungkin dalam kasus Anda tergantung pada situasi Anda) adalah pindah ke C ++ dan menggunakannya sebagai 'C yang lebih baik'. Anda dapat menggunakan C ++ tanpa menggunakan kelas, templat, overloading operator atau fitur canggih lainnya.
Ini akan memberi Anda varian C dengan kelebihan fungsi dan parameter default (dan fitur apa pun yang Anda pilih untuk digunakan). Anda hanya perlu sedikit disiplin jika Anda benar-benar serius hanya menggunakan subset terbatas dari C ++.
Banyak orang akan mengatakan itu ide yang buruk untuk menggunakan C ++ dengan cara ini, dan mereka mungkin ada benarnya. Tapi itu hanya sebuah opini; Saya pikir itu sah untuk menggunakan fitur C ++ yang Anda merasa nyaman tanpa harus membeli semuanya. Saya pikir bagian penting dari alasan keberhasilan C ++ adalah bahwa itu digunakan oleh banyak programmer di hari-hari awal persis seperti ini.
sumber
Namun opsi lain menggunakan
struct
s:sumber
Tidak.
sumber
20202020
dalam hex, tapi bagaimana cara mengetiknya?Trik lain menggunakan makro:
Jika hanya satu argumen yang diteruskan,
b
terima nilai default (dalam hal ini 15)sumber
Tidak, tetapi Anda mungkin mempertimbangkan untuk menggunakan serangkaian fungsi (atau makro) untuk memperkirakan menggunakan argumen default:
sumber
Ya, dengan fitur C99 Anda dapat melakukan ini. Ini berfungsi tanpa mendefinisikan struktur data baru atau lebih dan tanpa fungsi harus memutuskan pada saat runtime bagaimana namanya, dan tanpa overhead komputasi.
Untuk penjelasan terperinci lihat posting saya di
http://gustedt.wordpress.com/2010/06/03/default-arguments-for-c99/
Jens
sumber
Umumnya tidak, tetapi dalam gcc Anda dapat membuat parameter terakhir dari funcA () opsional dengan makro.
Dalam funcB () saya menggunakan nilai khusus (-1) untuk memberi sinyal bahwa saya memerlukan nilai default untuk parameter 'b'.
sumber
Saya meningkatkan jawaban Jens Gustedt sehingga:
variadic.h:
Skenario penggunaan yang disederhanakan:
Dan dengan _Generik:
Dan dengan pemilihan nama fungsi variadic, yang tidak dapat digabungkan dengan _Generic:
sumber
IYA
Melalui makro
3 parameter:
Jika Anda menginginkan argumen ke-4, maka my_func3 tambahan perlu ditambahkan. Perhatikan perubahan dalam VAR_FUNC, my_func2 dan my_func
4 Parameter:
Hanya pengecualian bahwa variabel float tidak dapat diberi nilai default ( kecuali jika itu adalah argumen terakhir seperti dalam kasus 3 parameter ), karena mereka memerlukan periode ('.'), Yang tidak diterima dalam argumen makro. Tapi bisa mencari cara kerja seperti yang terlihat di makro my_func2 ( dari 4 parameter kasus )
Program
Keluaran:
sumber
Ya, Anda dapat melakukan sesuatu secara bersamaan, di sini Anda harus mengetahui daftar argumen yang berbeda yang bisa Anda dapatkan tetapi Anda memiliki fungsi yang sama untuk menangani semuanya.
sumber
Kenapa kita tidak bisa melakukan ini.
Berikan nilai opsional pada argumen opsional. Dengan cara itu, pemanggil fungsi tidak perlu melewati nilai argumen. Argumen mengambil nilai default. Dan dengan mudah argumen itu menjadi opsional untuk klien.
Untuk misalnya
membatalkan foo (int a, int b = 0);
Di sini b adalah argumen opsional.
sumber