2011-11-09 41 views
6

Tôi có một hàm nhân hai ma trận A và B rồi in kết quả. Tôi nhận được hai kết quả đầu ra khác nhau khi chạy chương trình theo hai cách tương tự.đối số được đảo ngược cho hàm C

đầu tiên:

FILE *f; 
    f = fopen("in.txt","r"); 
    struct Mat* A = read_mat(f); 
    struct Mat* B = read_mat(f); 
    print_mat(mat_mul_1(A, B)); 

đầu ra là nhân chính xác của

A * B

thứ hai:

FILE *f; 
    f = fopen("in.txt","r"); 
    print_mat(mat_mul_1(read_mat(f), read_mat(f))); 

đầu ra là chính xác nhân của

B * Một

Tôi muốn biết lý do tại sao các đối số đã bị đảo ngược?!

(như chức năng 'mat_mul_1' là một hộp đen)

Trả lời

8

Bạn có mong đợi rằng read_mat(f) đầu tiên sẽ được đánh giá đầu tiên?

C không đảm bảo như vậy. Trình biên dịch là miễn phí để phát ra mã đánh giá các đối số theo bất kỳ thứ tự nào nó chọn.

Trình tự đánh giá của hàm vấn thiết kế, các đối số thực tế, và subexpressions trong các đối số thực tế là unspeci fi ed, nhưng có một điểm chuỗi trước khi cuộc gọi thực tế.

+0

Bạn có thể cho tôi biết tại sao trình biên dịch sẽ thay đổi thứ tự của các đối số? như tôi thấy rằng nó tốt hơn để luôn luôn đánh giá nó từ trái sang phải vì nó đã ra lệnh –

+1

không thực sự nó không nhất thiết phải "tốt hơn". Ví dụ, giả thuyết, nó có thể nhanh hơn để đẩy công cụ trên ngăn xếp trái sang phải và đánh giá kết quả dưới lên (vì vậy về cơ bản ngược lại). vấn đề là nếu đọc các vấn đề bạn nên đọc một cách rõ ràng. –

+1

@ M.ElSaka: Trình biên dịch nội bộ chuyển đổi một biểu thức thành một loại cấu trúc cây nhị phân, trong đó mỗi toán hạng tạo thành một "lá". Sau đó nó có thể đánh giá cây này bắt đầu từ lá bên trái hoặc bên phải nhất. Cái nào hiệu quả hơn trên một nền tảng cụ thể không rõ ràng, nếu nó quan trọng. Đây là lý do tại sao nó là hành vi không xác định. – Lundin

0

Đó là vì các thông số để các chức năng được đánh giá:

print_mat(mat_mul_1(A, B)); 

sẽ gọi mat_mul_1(A, B), trong đó A là ma trận đầu tiên trong file và B là lần thứ hai. Trong trường hợp thứ hai của bạn:

print_mat(mat_mul_1(read_mat(f), read_mat(f))); 

Tôi đoán (vì nó không theo quy định của tiêu chuẩn này) rằng, trên hệ thống của bạn, đang kêu gọi thứ hai read_mat() đầu tiên, và do đó sẽ gọi mat_mul_1(B, A);

0

Lý do là bên phải nhất là read_mat(f) được gọi trước nhất bên trái nhất, và do đó bạn đang đọc cấu trúc đầu tiên vào những gì bạn sẽ là B. Do đó, AB bị đảo ngược.

Tôi có ý nghĩa về nó trong các đối số đó được đẩy lên chồng ngược khi chúng được chuyển đến hàm, do đó chúng được đánh giá từ phải sang trái.

Tôi không chắc chắn có bất kỳ tiêu chuẩn xác định những gì phải được đánh giá đầu tiên.

0

Mã của bạn có hành vi không xác định vì FILE được trỏ đến bởi f được sửa đổi bởi cả hai đầu tiên và thứ hai read_mat(f) và không có điểm chuỗi tồn tại giữa hai sửa đổi này.

2

Lý do tại sao như những người khác đã chỉ ra, thứ tự đánh giá các tham số chức năng là hành vi không xác định, và do đó không nên dựa vào. Nhưng có một vấn đề khác, có thể nghiêm trọng ở đây:

Hàm read_mat có thể truy cập tài nguyên tĩnh, chẳng hạn như biến tĩnh/toàn cục và sau đó trả về giá trị của chúng. Như thế này:

static int x; 

int inc (void) 
{ 
    x++; 
    return x; 
} 

printf("%d %d", inc(), inc()); 

Kết quả thực tế của hàm sẽ thay đổi tùy theo thứ tự đánh giá.

(Đoạn mã này được lấy từ một bài kiểm tra phỏng vấn tôi sử dụng khi thuê lập trình viên C. Tôi hỏi đầu ra của mã này là gì và câu trả lời đúng là "2 1" hoặc "1 2". cho dù lập trình viên C biết về các khái niệm khởi tạo tĩnh và thứ tự đánh giá.)