C'de iç içe geçmiş işlev


97

C'de iç içe geçmiş bir fonksiyona sahip olabilir miyiz? İç içe geçmiş işlevlerin kullanımı nedir? C de varlarsa, uygulamaları derleyiciden derleyiciye farklılık gösterir mi?



Yanıtlar:



36

Hayır, C'de yoklar.

Pascal gibi dillerde (en az) iki nedenden dolayı kullanılırlar:

  1. Ad alanlarını kirletmeden işlevsel ayrıştırmaya izin verirler. Sorunu daha küçük, mantıksal parçalara ayırmak için bir veya daha fazla iç içe işlevi kullanarak bazı karmaşık mantıkları uygulayan, genel olarak görülebilen tek bir işlev tanımlayabilirsiniz.
  2. Bazı durumlarda parametre geçişini basitleştirir. İç içe geçmiş bir işlevin tüm parametrelere ve dış işlevin kapsamındaki değişkenlerin bir kısmına veya tümüne erişimi vardır, bu nedenle dış işlevin iç içe geçmiş işleve açıkça bir yerel durum yığını geçirmesi gerekmez.

21

İç içe geçmiş işlevler ANSI C'nin bir parçası değildir , ancak bunlar Gnu C'nin parçasıdır .


Gnu C'nin bir parçası olsalar ne önemi var
Sachin Chourasiya

4
@Sachin İç içe geçmiş işlevlere sahip C kodunun neden gcc ile derlenebileceğini anlamaya yardımcı olur. Bilginin eğitim değeri vardır. Dahası, soru yalnızca C89, C99 veya GNU C ile mi sınırlı olduğunu
belirtmiyor

4
GCC tarafından desteklenen diğer dillerde (benim bildiğim ADA ve Pascal) var, bu nedenle ya C uygulamasına eklemek kolaydı ya da destekleyici diller için hazırlık yapmak amacıyla C'ye eklenmiş olabilir. onları gerektirir.
nategoose

MATLAB ayrıca iç içe geçmiş işlevlere sahiptir.
mikeTronix

17

Hayır, içinde yuvalanmış bir işleve sahip olamazsınız C. Gelebileceğiniz en yakın şey, başka bir işlevin tanımı içinde bir işlev bildirmektir. Yine de, bu işlevin tanımı başka herhangi bir işlev gövdesinin dışında görünmelidir.

Örneğin

void f(void)
{
    // Declare a function called g
    void g(void);

    // Call g
    g();
}

// Definition of g
void g(void)
{
}

6
G fonksiyonu bu şekilde bildirilirse, kapsamı ne olur?
Sachin Chourasiya

6
Bildirimin kapsamı diğer tüm bildirimler gibi, yani bu durumda işlevin sonuna kadar. Elbette, tanımı gdaha sonra dosyada göründüğünde, deklarasyon çeviri biriminin geri kalanı için kapsam dahilindedir. Buna ek olarak yapabilirsiniz bu tavsiye edilmez bile kapsamda görünür bir bildiri olmadan C işlevleri çağırmak.
CB Bailey

5

Bundan bahsediyorum, çünkü C kodlama yapan birçok kişi artık bunu yapmak için C ++ derleyicileri (Visual C ++ ve Keil uVision gibi) kullanıyor, bu yüzden bundan faydalanabilirsiniz ...

Henüz C'de izin verilmese de, C ++ kullanıyorsanız, C ++ 11'de sunulan lambda işlevleriyle aynı etkiyi elde edebilirsiniz:

void f()
{
    auto g = [] () { /* Some functionality */ }

    g();
}

4
Soru C ++, değil C hakkında özellikle idi
Virgile

11
@Virgile - Soru ayrıca özellikle "İç içe işlevlere başka herhangi bir dilde izin veriliyor mu?" Jon'un cevabı bana yardımcı oldu.
www-0av-Com

3

Diğerlerinin de yanıtladığı gibi, standart C yuvalanmış işlevleri desteklemez.

İç içe geçmiş işlevler, bazı dillerde, birden çok işlevi ve değişkeni bir kapta (dış işlev) içine almak için kullanılır, böylece tek tek işlevler (dış işlev hariç) ve değişkenler dışarıdan görülmez.

In C , bu ayrı bir kaynak dosyada tür fonksiyonları koyarak yapılabilir. Ana işlevi global, diğer tüm işlevleri ve değişkenleri statik olarak tanımlayın . Artık bu modülün dışında yalnızca ana işlev görülebilir.


Eğer özyineleme varsa outer-> nested-> outer-> nested, o zaman tutan iki farklı çerçeve olacaktır int declared_in_outer, bu yüzden sadece declared_in_outerstatik bir global olarak koyamazsınız .
Adrian Panasiuk

1

İkinci sorunuzu cevaplamak için, iç içe geçmiş işlevleri tanımlamaya izin veren diller vardır (burada bir liste bulunabilir: yuvalanmış işlevler-dil-listesi-wikipedia ).

Bu dillerin en ünlülerinden biri olan JavaScript'te, iç içe geçmiş işlevlerden biri (kapanışlar denir) şunlardır:

  • Nesnelerin yapıcılarında sınıf yöntemleri oluşturmak için.
  • Ayarlayıcılar ve alıcılarla birlikte özel sınıf üyelerinin işlevselliğini elde etmek için.
  • Küresel isim alanını kirletmemek (tabii ki her dil için geçerli).

birkaç isim...


0

Ya da bu konuda akıllı davranabilir ve ön işlemciyi kendi yararınıza kullanabilirsiniz ( source.c):

#ifndef FIRSTPASS
#include <stdio.h>

//here comes your "nested" definitions
#define FIRSTPASS
#include "source.c"
#undef FIRSTPASS

main(){
#else
    int global = 2;
    int func() {printf("%d\n", global);}
#endif
#ifndef FIRSTPASS
    func();}
#endif

-1

bu C'deki iç içe geçmiş bir işlev değil mi? (displayAccounts () işlevi)

İşlevi farklı şekilde tanımlayıp değişkenler geçirebileceğimi ve hesapların birden çok kez yazdırılması gerektiğinden neyin işe yaramadığını biliyorum.

(bir okul ödevinden alınan pasaj) ...

//function 'main' that executes the program.
int main(void)
{
    int customerArray[3][3] = {{1, 1000, 600}, {2, 5000, 2500}, {3, 10000, 2000}};  //multidimensional customer data array.
    int x, y;      //counters for the multidimensional customer array.
    char inquiry;  //variable used to store input from user ('y' or 'n' response on whether or not a recession is present).

    //function 'displayAccounts' displays the current status of accounts when called.
    void displayAccounts(void)
    {
        puts("\t\tBank Of Despair\n\nCustomer List:\n--------------");
        puts("Account #    Credit Limit\t  Balance\n---------    ------------\t  -------");
        for(x = 0; x <= 2; x++)
        {
            for(y = 0; y <= 2; y++)
                printf("%9d\t", customerArray[x][y]);
            puts("\n");
        }
    }

    displayAccounts();  //prints accounts to console.
    printf("Is there currently a recession (y or n)? ");


//...

    return 0;
}

4
Yasal standart C değildir. Derleyicinizle çalışıyorsa, bunun nedeni derleyicinizin standart C diline bir uzantı sağlamış olmasıdır; bir anlamda derleyiciniz farklı bir dil derliyor, bu kesinlikle C değil.
Nate Eldredge

katkılarınız için teşekkür ederim. O zamandan beri işlevleri bildirmenin, tanımlamanın ve kullanmanın doğru yolunu öğrendim. bu> 'a bakmak biraz utanç verici. <
midnightCoder

1
@midnightCoder: Cevabınızı her zaman silebilirsiniz :)
chqrlie
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.