2011-12-30 33 views
116

Tôi chỉ đọcTại sao chính không trả về 0 ở đây?

ISO/IEC 9899: 201x Ủy ban Dự thảo - 12 tháng tư 2011

trong đó tôi tìm thấy dưới chấm dứt chương trình 5.1.2.2.3

..reaching the } that terminates the main function returns a value of 0. 

nó có nghĩa là nếu bạn không chỉ định bất kỳ câu lệnh trả về nào trong số main() và nếu chương trình chạy thành công, thì tại dấu ngoặc ôm} của chính sẽ trả về 0.

Nhưng trong foll do i mã không chỉ định bất kỳ tuyên bố trở lại, nhưng nó không trả lại 0

#include<stdio.h> 
int sum(int a,int b) 
{ 
return (a + b); 
} 

int main() 
{ 
    int a=10; 
    int b=5; 
    int ans;  
    ans=sum(a,b); 
    printf("sum is %d",ans); 
} 

biên dịch

gcc test.c 
./a.out 
sum is 15 
echo $? 
9   // here it should be 0 but it shows 9 why? 
+0

Bạn đã biên dịch bằng trình biên dịch C99 (hoặc lớn hơn) chưa? – pmg

+69

+1 vì có sự kiên nhẫn để đọc thông số kỹ thuật ..... – Asher

+0

tôi có biên dịch với gcc không có tùy chọn/cờ bổ sung? –

Trả lời

140

quy tắc đó đã được bổ sung trong phiên bản 1999 của tiêu chuẩn C. Trong C90, trạng thái trả về là không xác định.

Bạn có thể bật tính năng này bằng cách chuyển -std=c99 tới gcc.

Như một lưu ý phụ, thú vị 9 được trả về vì đó là sự trở lại của printf mà chỉ viết 9 ký tự.

+8

cảm ơn bạn. gcc -std = c99 test.c cho 0 –

+40

Hoặc bạn chỉ có thể thêm 'return 0;' trước khi đóng '}'. Nó vô hại và làm cho chương trình của bạn di động với các trình biên dịch cũ hơn. –

+0

không} của chính sẽ trả về 0 được thêm vào trong c99 hoặc một phần của phiên bản cũ hơn của c? –

15

Nó trả về giá trị trả về là printf là số ký tự thực sự được in ra.

+0

câu hỏi không nói về những gì được in trong consolewhen thực hiện chương trình, nó nói về giá trị trả về của chương trình: (bạn có thể lấy nó trong linux với lệnh schell: echo $? Và trong windows với: echo% errorlevel%) –

+1

@eharvest Mặc dù tôi không biết cách kiểm tra '% errorlevel%' trong Windows, bất kỳ sự khác biệt nào giữa mã thoát và giá trị trả về của 'main' trong linux? –

+1

@eharvest: Câu trả lời cũng không nói về nội dung được in trong bảng điều khiển. Nó nói về giá trị _return_ của 'printf' mà trong trường hợp này là 9 mà sau đó được" thăng chức "như mã thoát từ' main' bằng cách nào đó khi sử dụng một số phiên bản gcc. –

6

Giá trị trả lại từ một hàm thường được lưu trữ trong thanh ghi eax của CPU, do đó, câu lệnh "return 4;" thường sẽ biên dịch để

mov eax, 4; 
ret; 

và trở về x (tùy thuộc vào trình biên dịch của bạn) sẽ là một cái gì đó như:

mov eax, [ebp + 4]; 
ret; 

nếu bạn không chỉ định một giá trị trả về sau đó trình biên dịch vẫn sẽ nhổ ra " ret "nhưng không thay đổi giá trị của eax. Vì vậy, người gọi sẽ nghĩ rằng những gì đã từng còn lại trong thanh ghi eax trước đó là giá trị trả về. Đối với ví dụ này, nó thường sẽ là giá trị trả về printf, nhưng các trình biên dịch khác nhau sẽ tạo ra mã máy khác nhau và sử dụng một số thanh ghi khác nhau.

Đây là giải thích đơn giản, các quy ước gọi điện khác nhau và nền tảng đích sẽ đóng vai trò quan trọng nhưng cần đủ thông tin để giải thích những gì đang diễn ra 'hậu trường' trong ví dụ của bạn.

Nếu bạn đã có một sự hiểu biết cơ bản về trình biên dịch, bạn nên so sánh việc tháo gỡ các trình biên dịch khác nhau. Bạn có thể thấy rằng một số trình biên dịch đang xóa thanh ghi eax làm bảo vệ.

+11

Trình biên dịch _might_ làm điều đó. Nó không xác định. Thay vào đó, nó có thể chọn bắn bạn vào đầu bằng hộp mực máy in. –

+0

@LightnessRacesinOrbit undefined không giống như không thể đoán trước, tức là từ "nếu trình biên dịch X, nó sẽ là tiêu chuẩn phù hợp" nó không hợp lý theo "trình biên dịch có thể làm X" – Owen

+0

@Owen: Trích dẫn đoạn tiêu chuẩn xác định điều này. –

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