2013-07-04 33 views
7

Ví dụ:Thực hiện năng suất trong C

int getNext(int n) { 
    while (TRUE) { 
     n = n+1; 
     yield n; 
    } 
} 

int main() { 
    while (TRUE) { 
     int n = getNext(1); 
     if (n > 42) 
      break; 
     printf("%d\n",n); 
    } 
} 

như vậy rằng mã trên sẽ in tất cả các số từ 1 đến 42. Tôi nghĩ làm yield thay đổi địa chỉ của GetNext để hướng dẫn sau yield. Nhưng tôi không thể hiểu làm thế nào tôi sẽ lưu bối cảnh (đăng ký/biến) kể từ khi ngăn xếp sẽ được chạy qua bởi các chức năng người gọi.

Lưu ý:

Tôi nhận thấy rằng mã ở trên có thể dễ dàng được triển khai bởi biến tĩnh, nhưng đó không phải là vấn đề.

+0

Tuy nhiên bạn làm điều đó, bạn sẽ không thể làm điều đó với sự dễ dàng của cú pháp C# (hoặc bất kỳ thứ gì). Đây là những biến ngữ cảnh và các con trỏ hàm. – Joe

+1

@Joe Đây là học thuật thuần túy, chỉ cần tự hỏi ý tưởng chung là gì. – Shmoopy

+0

Hãy xem '' có thể. –

Trả lời

10

Bạn có thể làm như vậy, ngay cả trong di C. Dưới đây là một ví dụ thô mà làm việc (gcc -Wall gen.c):

#include <stdbool.h> 
#include <stdio.h> 
#include <setjmp.h> 

#define YIELD(func, n) if (! setjmp(func##_gen_jmp)) { \ 
     func##_ret = n;         \ 
     longjmp(func##_caller_jmp, 1);     \ 
    } 


#define GENERATOR(ret, func, argt, argv)  \ 
    static jmp_buf func##_caller_jmp;    \ 
    static jmp_buf func##_gen_jmp;    \ 
    static bool func##_continue=false;   \ 
    static ret func##_ret;      \ 
               \ 
    void func##__real(argt argv);     \ 
               \ 
    ret func(argt argv) {       \ 
    if (!func##_continue) {      \ 
    func##_continue=true ;      \ 
     if (! setjmp(func##_caller_jmp)) {  \ 
     func##__real(argv);      \ 
     } else {         \ 
     return func##_ret;      \ 
     }           \ 
    }           \ 
    else {          \ 
     longjmp(func##_gen_jmp,1);    \ 
    }           \ 
    return 0;         \ 
    }            \ 
    void func##__real(argt argv) 



GENERATOR(int, getNext, int, n) { 
    static int counter; 

    counter = n; 
    while (true) { 
     counter = counter+1; 
     YIELD(getNext, counter); 
    } 
} 

int main() { 
    while (true) { 
     int n = getNext(1); 
     if (n > 42) 
      break; 
     printf("%d\n",n); 
    } 
    return 0; 
} 
1

Những gì bạn đang tìm kiếm được gọi là "coroutines" và (ít nhất là không mất tổng quát — xem câu trả lời khác cho phương pháp để thực hiện trong trường hợp giới hạn) là không thể trong di động C. một số thủ thuật mà bạn có thể giả mạo chúng; xem http://en.wikipedia.org/wiki/Coroutine#Implementations_for_C đối với một số.

Các vấn đề liên quan