2012-03-16 40 views
26

Tôi đang viết một số mã C và trong mã của tôi, tôi có hai vòng lồng nhau. Trên một điều kiện cụ thể, tôi muốn break ra khỏi vòng lặp bên trong và continue vòng ngoài. Tôi đã cố gắng để đạt được điều này bằng cách sử dụng một nhãn ở cuối trên mã vòng lặp bên ngoài và, trên điều kiện, goto nhãn đó. Tuy nhiên gcc đưa ra một lỗi mà tôi không thể có nhãn ở cuối câu lệnh ghép. Tại sao không?Trong C tại sao bạn cần một tuyên bố sau một nhãn goto?

Lưu ý 1: Đây không phải là tuyên bố switchrằng câu hỏi đã được trả lời elsewhere.

Lưu ý 2: Đây không phải là câu hỏi về phong cách và tôi có nên hay không nên sử dụng các câu lệnh goto hoặc biến điều kiện để thay thế.

EDIT: Người dân đã yêu cầu một ví dụ và tôi có thể cung cấp cho một ví dụ hơi dễ dãi kiểm tra nếu một mảng là một mảng con của mảng khác

int superArray[SUPER_SIZE] = {...}, subArray[SUB_SIZE] = {...}; 
    int superIndex, subIndex; 

    for (superIndex=0; superIndex<SUPER_SIZE-SUB_SIZE; superIndex+=1) 
    { 
     for (subIndex=0; subIndex<SUB_SIZE; subIndex+=1) 
     if (superArray[superIndex+subIndex] != subArray[subIndex]) 
      goto break_then_continue; 

     // code that executes if subArray is a sub array 

     break_then_continue: 
    } 
+3

bạn có thể cung cấp một chương trình nhỏ mà tái tạo thông báo lỗi bạn nhận được? – sarnold

+0

chúc may mắn và xem ra cho velociraptors – wim

Trả lời

34

Trong tiêu chuẩn nó một cách rõ ràng nói rằng nhãn thuộc về một tuyên bố, do đó một dấu chấm phẩy đơn giản (;) sau khi bạn nhãn có thể phá vỡ sự cố bạn đang chạy đến, vì đó được tính là một tuyên bố.

Có thậm chí là một ví dụ về việc sử dụng một "trống" tuyên bố trong 6.8.3/6.

VÍ DỤ 3 Một tuyên bố rỗng cũng có thể được sử dụng để thực hiện một nhãn chỉ trước khi bế mạc} của một câu lệnh ghép

while (loop1) { 
    /* ... */ 

    while (loop2) { 
    /* ... */ 

    if (want_out) 
     goto end_loop1; 

    /* ... */ 
    } 

    /* ... */ 

    end_loop1: ; 
} 

Trong tiêu chuẩn này được gọi là null statement.


6.8.1 báo cáo đã được gán nhãn

Syntax 
    1 labeled-statement: 
     identifier : statement 
     case constant-expression : statement 
     default : statement 

ý rằng statement là không bắt buộc trong ngoặc kép ở trên.


+0

+1 Câu trả lời hay. Yêu ví dụ lấy thẳng từ tiêu chuẩn. – Caleb

+0

Cảm ơn bạn đã phản hồi rất tốt. Tôi đã tìm kiếm * tại sao * 'gcc' hoạt động theo cách nó không làm thế nào để có được xung quanh nó. Tuy nhiên phản ứng của bạn có xu hướng chỉ ra rằng nó chỉ đơn giản là cách c được viết. Điều này phần lớn là một di sản từ khi biên dịch c chỉ là một sự trừu tượng nhỏ của mã assembly. – AntonDelprado

+0

@AntonDelprado Nó thực sự khá đơn giản, goto sẽ đặt nhãn trước khi lệnh/biểu hiện và nếu không có điều đó, không có nơi nào để nhảy. Đó là tuyên bố trống được sử dụng để điều này là có thể. như thế này bạn nhảy vào một số tương đương vô hại của chức năng lắp ráp NOP (không hoạt động). – AoeAoe

3

Bạn chỉ cần viết:

label: ; 

Dấu chấm phẩy là một câu lệnh trống. Bạn cần nó bởi vì ngôn ngữ được định nghĩa như thế; bạn cần phải đi đến một tuyên bố, ngay cả khi nó là một cái trống.

for (int i = 0; i < N; i++) 
    { 
     for (int j = 0; i < M; j++) 
     { 
      ... 
      if (some_condition) 
       goto continue_loop1; 
      ... 
     } 
continue_loop1: ; 
    } 

Bạn có thể tranh luận về sự thụt lề trên nhãn.

+0

Cũng lưu ý rằng một tuyên bố, ngay cả với khởi tạo, không phải là một tuyên bố có thể được dán nhãn: 'label1: int x = function (y, z);' không hợp lệ. –

3

Nhãn phải trỏ đến tuyên bố.

C nhiệm vụ này:

(C99, 6.8.1 báo cáo đã được gán nhãn P4) " Bất kỳ tuyên bố có thể được đi trước bởi một tiền tố khai báo một định danh như một tên nhãn."

Trong trường hợp của bạn, bạn có thể sử dụng một lệnh rỗng:

void foo(void) 
{ 
    goto bla; 

    bla: 
    ; 
} 

báo cáo Null thực hiện không hoạt động.

Hoặc bạn cũng có thể sử dụng một câu lệnh ghép (một khối) nếu bạn có khai báo:

void foo(void) 
{ 
    goto bla; 

    bla: 
    { 
     int x = 42; 
     printf("%d\n", x); 
    } 
} 
Các vấn đề liên quan