Apa arti tanda kurung di sekitar nama fungsi?

214

Di salah satu file sumber proyek saya, saya menemukan definisi fungsi C ini:

int (foo) (int *bar)
{
    return foo (bar);
}

Catatan: tidak ada tanda bintang di sebelahnya foo, jadi itu bukan penunjuk fungsi. Atau itu? Apa yang terjadi di sini dengan panggilan rekursif?

pengguna1859094
sumber
7
Tidak, ini bukan pointer fungsi - ini masih fungsi biasa bernama foo.
Nemanja Boric
Apakah ini fungsi yang lengkap?
asheeshr
2
apakah Anda memiliki bukti bahwa fungsi ini digunakan dalam konteks yang bermanfaat?
moooeeeep
1
... sepertinya beberapa fungsi dummy yang mungkin hanya ditulis untuk melihat apakah ia mengkompilasi, pada sumber yang ada, dan seharusnya dihapus. Saya akan menghapusnya (jika itu adalah fungsi sebenarnya), karena paling-paling itu akan menjadi loop tak terbatas (saya tidak yakin apakah kompiler C diizinkan untuk mengoptimalkan panggilan ekor untuk melompat), paling buruk stack overflow.
hyde
3
Tanda kurung dalam deklarasi C membantu untuk mengubah bahasa yang ambigu. Cepat, apa itu a(b);? Deklarasi bsebagai variabel tipe a? Atau panggilan untuk berfungsi adengan argumen b? Perbedaannya adalah sintaksis, dan Anda tidak dapat mengetahui cara untuk menguraikannya tanpa melihat info deklarasi a; yaitu tanda kurung fungsi postfix, atau tanda kurung opsional di sekitar deklarator.
Kaz

Jawaban:

329

Dengan tidak adanya hal-hal preprosesor yang terjadi, footanda tangan setara dengan

int foo (int *bar)

Satu-satunya konteks di mana saya telah melihat orang menempatkan tanda kurung yang tampaknya tidak perlu di sekitar nama fungsi adalah ketika ada fungsi dan makro seperti fungsi dengan nama yang sama, dan programmer ingin mencegah ekspansi makro.

Praktek ini mungkin tampak sedikit aneh pada awalnya, tetapi perpustakaan C menetapkan preseden dengan menyediakan beberapa makro dan fungsi dengan nama yang identik .

Satu pasangan fungsi / makro adalah isdigit(). Perpustakaan mungkin mendefinisikannya sebagai berikut:

/* the macro */
#define isdigit(c) ...

/* the function */
int (isdigit)(int c) /* avoid the macro through the use of parentheses */
{
  return isdigit(c); /* use the macro */
}

Fungsi Anda terlihat hampir sama dengan yang di atas, jadi saya curiga ini juga terjadi pada kode Anda.

NPE
sumber
2
Itu mungkin juga terjadi di sini; Saya tidak mencari makro ... Dan saya tidak tahu bahwa ekspansi makro tidak terjadi dalam tanda kurung, Terima kasih telah menunjukkannya!
user1859094
13
@ user1859094: Pada tampilan kedua, ini hampir pasti apa yang terjadi pada kode Anda. Bagian foo(bar)dalam fungsi menggunakan makro yang sesuai.
NPE
78
@ user1859094 ekspansi makro memang terjadi di dalam tanda kurung, tetapi ekspansi makro seperti fungsi hanya terjadi jika token berikutnya adalah tanda kurung kiri (C99, 6.10.3§10), sehingga foo (int* bar)akan diganti, tetapi tidak (foo) (int *bar)(token berikutnya) setelah fooadalah ))
Virgile
4
Bagaimana fungsi seperti itu disebut? Apakah Anda akan menyebutnya dengan tanda kurung juga? Misalnya, apakah ini akan berfungsi (isdigit)(5):?
gcochard
4
@Reg: Benar, begitulah cara Anda menyebutnya.
NPE
37

Paranthes tidak mengubah deklarasi - itu hanya mendefinisikan fungsi biasa yang disebut foo.

Alasan bahwa mereka telah digunakan hampir pasti karena ada fungsi-seperti makro yang disebut foodefined:

#define foo(x) ...

Menggunakan (foo)dalam deklarasi fungsi mencegah makro ini diperluas di sini. Jadi apa yang mungkin terjadi adalah bahwa suatu fungsi foo()sedang didefinisikan dengan tubuhnya sedang diperluas dari makro seperti fungsi foo.

kaf
sumber
5
Pengurangan yang bagus (meskipun menggunakan tanda kurung untuk tujuan ini harus dapat dihukum oleh hukum).
ugoren
3
@ugoren: menggunakan parens di sekitar nama fungsi adalah satu-satunya cara untuk mencegah ekspansi makro untuk makro seperti fungsi. Kadang-kadang itu alat yang diperlukan.
Michael Burr
7
@MichaelBurr, ada juga opsi untuk tidak memiliki makro dan fungsi dengan nama yang sama. Saya tahu Anda tidak bisa selalu mengendalikan semuanya, tetapi jika Anda mencapai solusi ini, saya akan mengatakan ada sesuatu yang sangat salah.
ugoren
-3

Tanda kurung tidak ada artinya.
Kode yang Anda perlihatkan hanyalah rekursi tak terbatas.

Saat mendefinisikan pointer fungsi, Anda terkadang melihat tanda kurung aneh yang berarti sesuatu. Tapi ini bukan masalahnya.

ugoren
sumber
6
Jelas tidak; kurung mencegah ekspansi makro. Lihat jawaban yang diterima.
Kevin
12
@ Kevin, Jawaban saya adalah tentang kode yang ditampilkan, dan sudah benar untuk itu. Di hampir semua pertanyaan C di sini, dengan asumsi definisi preprosesor yang tidak diketahui dapat mengubah segalanya. Dalam hal ini, jawaban yang menganggap preprosesor memang lebih baik, tetapi itu tidak membuat saya salah.
ugoren