2012-01-26 58 views
5

tôi đã phải đối mặt với một mẫu tiếp theo:nhiều giá trị trở lại trong chức năng

#include <stdio.h> 

// test multiple return                                        
int foo() 
{ 
    return 1,2,3,4,5,6; 
} 

// main entry point                                         
int main(int argc, char* argv[]) 
{ 
    printf("foo returns: %d\n", foo()); 
    return 0; 
} 

biên dịch nó, sau đó chạy:

gcc main.cpp -o main 
./main 

Kết quả là khó hiểu với tôi:

foo returns: 6 

Câu hỏi đặt ra là: tại sao không có lỗi thời gian biên dịch?

Trả lời

10

Bởi vì bạn đang sử dụng comma operator: biểu thức a,b nơi ab là tùy ý (thường là phụ-thực) tiểu biểu thức có nghĩa là: đánh giá phía bên tay trái a và loại bỏ kết quả của nó (vì vậy a chỉ đánh giá về mặt -Hiệu ứng), sau đó đánh giá b và cung cấp kết quả.

Bạn không thể trả lại nhiều thứ từ một hàm C. Bạn nên quay lại, ví dụ: tổng hợp (thường là struct) hoặc một con trỏ được phân bổ theo kiểu động.

Đối với câu hỏi, tại sao trình biên dịch không nói gì? Bởi vì bạn không hỏi nó. Bạn thực sự cần biên dịch với gcc -Wall (cho mã C) hoặc g++ -Wall (đối với C++ code), và sau đó bạn nhận được cảnh báo:

egor7.c: In function ‘foo’: 
egor7.c:6:13: warning: left-hand operand of comma expression has no effect [-Wunused-value] 
egor7.c:6:15: warning: left-hand operand of comma expression has no effect [-Wunused-value] 
egor7.c:6:17: warning: left-hand operand of comma expression has no effect [-Wunused-value] 
egor7.c:6:19: warning: left-hand operand of comma expression has no effect [-Wunused-value] 
egor7.c:6:21: warning: left-hand operand of comma expression has no effect [-Wunused-value] 
11

Trong bối cảnh này:

return 1,2,3,4,5,6; 

thực sự là comma operator. Nó đánh giá mọi thứ giữa dấu phẩy theo thứ tự (từ trái qua phải) và trả về dấu phẩy cuối cùng.

Đó là lý do tại sao nó trả về và in 6. Vì vậy, có, đó là mã hợp lệ. Đó là lý do tại sao không có lỗi trình biên dịch. (Mặc dù phần 1,2,3,4,5 không làm gì trong trường hợp này.)

Trong C và C++, bạn không thể trả về nhiều giá trị. Bạn sẽ phải sử dụng một cấu trúc hoặc một lớp để làm điều đó.

4

Khi nghi ngờ, sử dụng Clang:

$ clang++ -Weverything test.cpp 
test.cpp:4:5: warning: no previous prototype for function 'foo' [-Wmissing-prototypes] 
int foo() 
    ^
test.cpp:6:10: warning: expression result unused [-Wunused-value] 
    return 1,2,3,4,5,6; 
     ^
test.cpp:6:12: warning: expression result unused [-Wunused-value] 
    return 1,2,3,4,5,6; 
     ^
test.cpp:6:14: warning: expression result unused [-Wunused-value] 
    return 1,2,3,4,5,6; 
      ^
test.cpp:6:16: warning: expression result unused [-Wunused-value] 
    return 1,2,3,4,5,6; 
      ^
test.cpp:6:18: warning: expression result unused [-Wunused-value] 
    return 1,2,3,4,5,6; 
       ^
6 warnings generated. 

Như tên của nó , -Weverything kích hoạt mọi cảnh báo có sẵn. Bằng cách này bạn không phải nhớ các nhóm họ đang ở.

Để giải thích: hãy xem câu trả lời của Mysticial về toán tử dấu phẩy và các hiệu ứng trình tự của nó. Một lần xuất hiện hữu ích của toán tử này là:

std::list<Item> list = /**/; 
assert(list.size() >= 10); 

auto it = list.begin(); 
for (int i = 0; i < 10; ++i, ++it) { 
    std::cout << "Item " << i << ": " << *it << "\n"; 
} 

Sử dụng toán tử dấu phẩy để thực hiện hai thao tác trong một câu lệnh.

Tất nhiên, cú pháp đó chủ yếu là giai thoại, vì vậy mọi người thường xuyên bị bất ngờ ...

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