Hàm lồng nhau trong C


93

Chúng ta có thể có một hàm lồng nhau trong C không? Việc sử dụng các hàm lồng nhau là gì? Nếu chúng tồn tại trong C thì việc triển khai của chúng có khác gì từ trình biên dịch này sang trình biên dịch khác không?


1
Có vẻ là một bản sao của: stackoverflow.com/questions/1348095/…
zoli2k,

Câu trả lời:



36

Không, chúng không tồn tại trong C.

Chúng được sử dụng trong các ngôn ngữ như Pascal vì (ít nhất) hai lý do:

  1. Chúng cho phép phân hủy chức năng mà không gây ô nhiễm không gian tên. Bạn có thể xác định một hàm hiển thị công khai duy nhất thực hiện một số logic phức tạp bằng cách dựa vào một hoặc nhiều hàm lồng nhau để chia vấn đề thành các phần logic nhỏ hơn.
  2. Chúng đơn giản hóa việc truyền tham số trong một số trường hợp. Một hàm lồng nhau có quyền truy cập vào tất cả các tham số và một số hoặc tất cả các biến trong phạm vi của hàm bên ngoài, vì vậy hàm bên ngoài không phải chuyển một cách rõ ràng một đống trạng thái cục bộ vào hàm lồng nhau.

21

Chức năng lồng nhau không phải là một phần của ANSI C , tuy nhiên, họ là một phần của Gnu C .


Có ý nghĩa là gì nếu họ là một phần của Gnu C
Sachin Chourasiya

4
@Sachin Giúp nhận ra tại sao mã C với các hàm lồng nhau có thể được biên dịch bằng gcc. Thông tin có giá trị giáo dục. Hơn nữa, câu hỏi không quy định nếu nó được giới hạn chỉ để C89, C99 hoặc GNU C
zoli2k

4
Các ngôn ngữ khác được GCC hỗ trợ cũng có chúng (ADA và Pascal mà tôi biết), vì vậy có thể dễ dàng thêm vào việc triển khai C hoặc nó đã được thêm vào C để chuẩn bị cho các ngôn ngữ hỗ trợ yêu cầu họ.
nategoose

MATLAB cũng có các hàm lồng nhau.
mikeTronix 20/12/16

17

Không, bạn không thể có một hàm lồng trong C . Cách gần nhất bạn có thể đến là khai báo một hàm bên trong định nghĩa của một hàm khác. Tuy nhiên, định nghĩa của hàm đó phải xuất hiện bên ngoài bất kỳ thân hàm nào khác.

Ví dụ

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

    // Call g
    g();
}

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

6
Nếu hàm g được khai báo theo cách này, thì phạm vi của nó sẽ như thế nào?
Sachin Chourasiya

6
Khai báo có phạm vi giống như bất kỳ khai báo nào khác, vì vậy trong trường hợp này cho đến khi kết thúc hàm. Tất nhiên một khi định nghĩa của ghiển thị sau này trong tệp thì khai báo đó sẽ nằm trong phạm vi của phần còn lại của đơn vị dịch. Ngoài ra, bạn có thể gọi các hàm trong C mà không cần khai báo rõ ràng trong phạm vi ngay cả khi điều đó không được khuyến khích.
CB Bailey

5

Tôi đề cập đến vấn đề này vì nhiều người viết mã bằng C hiện đang sử dụng trình biên dịch C ++ (chẳng hạn như Visual C ++ và Keil uVision) để làm điều đó, vì vậy bạn có thể sử dụng ...

Mặc dù chưa được phép trong C, nếu bạn đang sử dụng C ++, bạn có thể đạt được hiệu quả tương tự với các hàm lambda được giới thiệu trong C ++ 11:

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

    g();
}

4
Câu hỏi đặt ra là đặc biệt về C, C ++ không
Virgile

11
@Virgile - Và câu hỏi cũng đã nêu cụ thể "Các hàm lồng nhau có được phép sử dụng trong bất kỳ ngôn ngữ nào khác không?". Câu trả lời của Jon đã giúp tôi.
www-0av-Com

3

Như những người khác đã trả lời, tiêu chuẩn C không hỗ trợ các hàm lồng nhau.

Các hàm lồng nhau được sử dụng trong một số ngôn ngữ để đưa nhiều hàm và biến vào một vùng chứa (hàm bên ngoài) để các hàm riêng lẻ (không bao gồm hàm bên ngoài) và các biến không bị nhìn thấy từ bên ngoài.

Trong C , điều này có thể được thực hiện bằng cách đưa các hàm như vậy vào một tệp nguồn riêng biệt. Định nghĩa hàm chính là toàn cục và tất cả các hàm và biến khác là tĩnh . Bây giờ chỉ có chức năng chính được hiển thị bên ngoài mô-đun này.


Nếu có đệ quy outer-> nested-> outer-> nested, thì sẽ có hai khung khác nhau đang giữ int declared_in_outer, vì vậy bạn không thể chỉ đặt declared_in_outerdưới dạng toàn cục tĩnh.
Adrian Panasiuk

1

Để trả lời câu hỏi thứ hai của bạn, có những ngôn ngữ cho phép xác định các hàm lồng nhau (có thể tìm thấy danh sách tại đây: nested-functions-language-list-wikipedia ).

Trong JavaScript, một trong những ngôn ngữ nổi tiếng nhất trong số những ngôn ngữ đó, một trong số các hàm lồng nhau (được gọi là bao đóng) là:

  • Để tạo các phương thức lớp trong các hàm tạo của các đối tượng.
  • Để đạt được chức năng của các thành viên lớp riêng cùng với setters và getters.
  • Không làm ô nhiễm không gian tên toàn cầu (tất nhiên là áp dụng cho mọi ngôn ngữ).

đến tên một vài...


0

Hoặc bạn có thể thông minh về nó và sử dụng bộ xử lý trước có lợi cho mình ( 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

đây không phải là một hàm lồng nhau trong C? (hàm displayAccounts ())

Tôi biết tôi có thể đã định nghĩa hàm theo cách khác và chuyển các biến và những gì không nhưng dù sao cũng hoạt động tốt khi tôi cần in các tài khoản nhiều lần.

(ảnh trích từ bài tập ở trường) ...

//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
Nó không phải là tiêu chuẩn pháp lý C. Nếu nó hoạt động với trình biên dịch của bạn, đó là vì trình biên dịch của bạn đã cung cấp phần mở rộng cho ngôn ngữ C tiêu chuẩn; trong một nghĩa nào đó trình biên dịch của bạn đang soạn thảo một ngôn ngữ khác nhau, đó là, nói đúng ra, không phải C.
Nate Eldredge

cảm ơn về thông tin bạn vừa nhập. Kể từ đó, tôi đã học được cách thích hợp để khai báo, định nghĩa và sử dụng các hàm. điều này hơi xấu hổ khi nhìn lại>. <
nửa

1
@midnightCoder: Bạn luôn có thể xóa câu trả lời của mình :)
chqrlie 5:19
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.