2011-01-10 67 views
15

Tại sao mã sau có đầu ra chính xác? int GGT không có câu lệnh trả về, nhưng mã không hoạt động? Không có biến toàn cục nào được đặt.Chức năng trả về giá trị không có lệnh return

#include <stdio.h> 
#include <stdlib.h> 

int GGT(int, int); 

void main() { 
    int x1, x2; 
    printf("Bitte geben Sie zwei Zahlen ein: \n"); 
    scanf("%d", &x1); 
    scanf("%d", &x2); 
    printf("GGT ist: %d\n", GGT(x1, x2)); 
    system("Pause"); 
} 

int GGT(int x1, int x2) { 
    while(x1 != x2) { 
     if(x1 > x2) { 
      /*return*/ x1 = x1 - x2; 
     } 
     else { 
      /*return*/ x2 = x2 - x1; 
     } 
    } 
} 
+6

Bật cấp cảnh báo ngay trên trình biên dịch của bạn, và bạn sẽ nhận được một tin nhắn ... –

+0

Tôi nhận được một thông báo cảnh báo, nhưng tôi là interessted tại sao nó hoạt động, trình biên dịch có đặt giá trị trả về không, không có ai? –

+1

trùng lặp có thể có của [hàm C được xác định là int nhưng không có câu lệnh trả về trong phần nội dung vẫn biên dịch] (http://stackoverflow.com/questions/4260048/c-function-defined-as-int-but-having-no- return-statement-in-the-body-still-compi) –

Trả lời

27

Đối với x86 ít nhất, giá trị trả lại của hàm này phải ở trong số eax đăng ký. Bất kỳ thứ gì ở đó sẽ được coi là giá trị trả lại của người gọi.

eax được sử dụng làm đăng ký trả lại, nó thường được sử dụng làm đăng ký "cào" bởi calee, bởi vì nó không cần phải được bảo tồn. Điều này có nghĩa rằng nó rất có thể là nó sẽ được sử dụng như bất kỳ biến địa phương nào. Bởi vì cả hai đều bằng nhau ở cuối, nên có thể có giá trị chính xác hơn trong eax.

+0

nơi là đăng ký eax ?? Cpu đăng ký ?? – Anjaneyulu

11

Nó không hoạt động và chắc chắn không hoạt động trên tất cả các trình biên dịch và hệ điều hành đích, ngay cả khi nó hoạt động trên máy của bạn.

Lời giải thích có khả năng là hàm trả về luôn trả về nội dung nào đó và thường là nội dung của thanh ghi. Nó có thể xảy ra rằng thanh ghi được sử dụng cho giá trị trả về là trong trường hợp của bạn giống như được sử dụng để tính toán biểu thức cuối cùng trước khi trở về từ hàm (trên các mục tiêu x86, chắc chắn là eax).

Điều này đang được nói, một trình biên dịch tối ưu hóa phát hiện rằng không có trở lại nào được phép loại bỏ hoàn toàn mã của hàm này. Từ đó, hiệu ứng bạn thấy (có thể) biến mất khi kích hoạt các mức tối ưu hóa cao hơn.

Tôi đã thử nghiệm nó với gcc:

gcc mà không cần tối ưu hóa: đầu vào 10, 20 -> kết quả là 10

gcc -O1 đầu vào 10, 20 -> kết quả là 1

gcc -O2 đầu vào 10, 20 -> kết quả là 0

+1

Có thể giải thích những gì anh ta tin hay không thích? – kriss

-3

Bạn không cần báo cáo trả lại nếu bạn đang sử dụng con trỏ. Nói chung, bạn chỉ có thể trả về một giá trị bằng câu lệnh Return, nhưng nếu bạn sử dụng con trỏ, bạn có thể trả về số lượng bạn muốn.

scanf ("% d", & x1); ở đó bạn cung cấp cho chức năng một địa chỉ của X1, không phải giá trị X1. con trỏ hoạt động địa chỉ rộng. bạn có thể đọc sách, để tìm hiểu cách hoạt động của con trỏ.

+0

Đừng nghĩ vậy, phạm vi biến cũng được đặt nếu tôi làm việc với con trỏ –

+1

Nhưng điều này không liên quan gì đến câu hỏi. –

+0

OH, xin lỗi, xin lỗi. Tôi nghĩ rằng đã được viết. GGT (& x1, & x2)) và int GGT (int * x1, int * x2). Tôi không đọc Mã, tôi cũng không đúng, xin lỗi. :) – VakhoQ

3

Trên x86 giá trị trả về được lưu trữ trong thanh ghi EAX, mà "vô tình" cũng được trình biên dịch này sử dụng để lưu trữ kết quả của phép tính số học (hoặc ít nhất là phép trừ). Bạn có thể kiểm tra điều này bằng cách nhìn vào lắp ráp được tạo ra bởi trình biên dịch của bạn. Tôi đồng ý với kriss - bạn không thể giả định điều này sẽ luôn xảy ra, vì vậy tốt hơn nên chỉ định rõ ràng giá trị trả về.

+0

Đừng nghĩ rằng điều này sẽ làm việc luôn, nhưng tôi đã quan tâm, tại sao nó hoạt động trong trường hợp này. Cảm ơn câu trả lời của bạn! –

0

GCC dán "ret" hướng dẫn trong trường hợp này, trong khi clang dán "ud2" và ứng dụng bị treo tại thời gian chạy.

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