İşlev adının çevresindeki parantezler ne anlama geliyor?


214

Proje kaynak dosyalardan birinde, bu C işlev tanımını buldum:

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

Not: yanında yıldız işareti yoktur foo, bu nedenle bir işlev işaretçisi değildir. Yoksa öyle mi? Burada özyinelemeli çağrıda neler oluyor?


7
Hayır, bir işlev işaretçisi değildir - hala foo adında normal bir işlevdir.
Nemanja Boric

Bu tam işlev mi?
asheeshr

2
Bu işlevin yararlı bir bağlamda kullanıldığına dair kanıtınız var mı?
moooeeeep

1
... mevcut kaynakta derlenip derlenmediğini ve kaldırılması gerekip gerekmediğini görmek için yazılmış bir kukla fonksiyona benziyor. En iyisi sonsuz döngü (çünkü C derleyicisi atlamak için kuyruk çağrısı optimize etmek için izin verilip verilmediğinden emin değilim), en kötü yığın taşması, onu (eğer bu işlev gerçekten ne yaparsa) kaldırmak.
hyde

3
C deklarasyonlarındaki parantezler dili belirsizleştirmeye yardımcı olur. Çabuk, nedir a(b);? bBir değişken türü olarak beyan a? Ya ada argümanla işlev çağrısı b? Fark sözdizimseldir ve bildirim bilgisine bakmadan bile ayrıştırmanın hangi yolunu bilemezsiniz a; yani bu postfix işlevi çağrı parantezleri veya bir bildirici çevresindeki isteğe bağlı parantezlerdir.
Kaz

Yanıtlar:


329

Herhangi bir önişlemci olayının yokluğunda, fooimzası şuna eşdeğerdir:

int foo (int *bar)

İşlev adlarının çevresine gereksiz görünen parantezler yerleştiren insanları gördüğüm tek bağlam, aynı ada sahip bir işlev ve işlev benzeri bir makro olduğunda ve programcı makro genişlemesini önlemek istiyor.

Bu uygulama ilk başta biraz garip gelebilir, ancak C kütüphanesi bazı makrolara ve işlevlere aynı adlar vererek emsal teşkil eder .

Böyle bir işlev / makro çifti isdigit(). Kütüphane kütüphaneyi şu şekilde tanımlayabilir:

/* 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 */
}

Fonksiyonunuz yukarıdakilerle neredeyse aynı görünüyor, bu yüzden kodunuzda neler olduğundan şüpheleniyorum.


2
Burada da böyle olabilir; Makroları aramadım ... Ve makro genişlemesinin parantez içinde gerçekleşmediğini bilmiyordum, İşaret ettiğiniz için teşekkürler!
user1859094

13
@ user1859094: İkinci bakışta, bu kesinlikle kodunuzda olup bitenler. foo(bar)İşlev içinde karşılık gelen makro kullanıyor.
NPE

78
@ user1859094 makro genişletmesi parantez içinde gerçekleşir, ancak işlev benzeri bir makronun genişletilmesi yalnızca bir sonraki belirteç sol parantezse (C99, 6.10.3§10) gerçekleşir foo (int* bar), ancak değiştirilmez (foo) (int *bar)(bir sonraki belirteç) sonra fooise ))
Virgile

4
Böyle bir fonksiyon nasıl adlandırılır? Parantez ile de çağırır mısın? Örneğin, bu işe yarar (isdigit)(5)mı?
gcochard

4
@Greg: Doğru, tam da böyle diyordunuz.
NPE

37

Parantezler beyanı değiştirmez - hala sadece denilen sıradan bir işlevi tanımlar foo.

Kullanılmasının nedeni neredeyse kesinlikle footanımlanmış olarak adlandırılan işlev benzeri bir makro olması nedeniyle :

#define foo(x) ...

Kullanılması (foo)işlev bildiriminde burada genişletilmektedir bu makro engeller. Dolayısıyla, gerçekleşmekte olan şey, bir işlev foo(), vücudu işlev benzeri makrodan genişletilerek tanımlanıyor olmasıdır foo.


5
Güzel bir kesinti (bu amaçla parantez kullanılması yasalarla cezalandırılmalıdır).
ugoren

3
@ugoren: işlev adı çevresinde parens kullanmak, işlev benzeri bir makro için makro genişletmesini önlemenin tek yoludur. Bazen gerekli bir araçtır.
Michael Burr

7
@MichaelBurr, aynı ada sahip bir makroya ve işleve sahip olmama seçeneği de var. Her şeyi her zaman kontrol edemeyeceğinizi biliyorum, ama bu çözüme ulaşırsanız, bir şeyin çok yanlış olduğunu söyleyebilirim.
ugoren

-3

Parantezler anlamsız.
Gösterdiğiniz kod sonsuz bir yinelemeden başka bir şey değildir.

Bir işlev işaretçisi tanımlarken, bazen bir şey ifade eden garip parantezler görürsünüz. Ama burada durum böyle değil.


6
Açıkçası hayır; parantezler makro genişlemesini engeller. Kabul edilen cevaba bakınız.
Kevin

12
@Kevin, Cevabım gösterilen kodla ilgili ve doğru. Buradaki hemen hemen her C sorusunda, bilinmeyen önişlemci tanımlarının varsayılması her şeyi değiştirebilir. Bu durumda, önişlemciyi düşünen cevaplar gerçekten daha iyidir, ancak benimkini yanlış yapmaz.
ugoren
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.