2013-08-22 50 views
7

Một câu hỏi được hỏi trong một thử nghiệm nhiều sự lựa chọn: Điều gì sẽ là đầu ra của chương trình sau đây:Turbo C++: Tại sao printf in giá trị dự kiến, khi không có biến nào được truyền cho nó?

#include <stdio.h> 

int main(void) 
{ 
    int a = 10, b = 5, c = 2; 

    printf("%d %d %d\n"); 

    return 0; 
} 

và những lựa chọn là hoán vị khác nhau là 10, 5, và 2. Đối với một số lý do, nó hoạt động trong Turbo C++, mà chúng tôi sử dụng trong trường đại học. Tuy nhiên, nó không phải khi biên soạn với gcc (trong đó đưa ra một cảnh báo khi -Wall được kích hoạt) hoặc kêu vang (trong đó có -Wformat kích hoạt và đưa ra một cảnh báo theo mặc định) hoặc trong Visual C++. Đầu ra là, như mong đợi, giá trị rác thải. Tôi đoán là nó có một cái gì đó để làm với thực tế là một trong hai Turbo C + + là 16-bit, và chạy trên Windows XP 32-bit, hoặc TCC là khủng khiếp khi nói đến tiêu chuẩn.

+9

Đầu ra có thể là bất kỳ thứ gì, vì mã này dẫn đến hành vi không xác định. –

+1

Vâng, toàn bộ trình biên dịch là một cá trích đỏ. –

+0

Trong công cụ định dạng gcc phải có tên biến, ví dụ printf ("% d", x); Nếu không printf sẽ in một số giá trị – sujin

Trả lời

20

Mã có undefined behaviour.

Trong Turbo C++, nó chỉ xảy ra khi ba biến số sống tại các vị trí chính xác trên ngăn xếp nơi thiếu đối số printf(). Điều này dẫn đến hành vi không xác định biểu hiện chính nó bằng cách có các giá trị "chính xác" được in.

Tuy nhiên, bạn không thể dựa vào điều này một cách hợp lý. Ngay cả sự thay đổi nhỏ nhất đối với môi trường xây dựng của bạn (ví dụ: các tùy chọn trình biên dịch khác nhau) có thể phá vỡ mọi thứ theo cách tùy tiện.

+0

Cảm ơn, điều này có ý nghĩa. Tôi đã thử cùng một chương trình (được biên dịch với gcc) vài lần trên Linux, và dường như sự trùng hợp này khá hiếm. Có phải sự trùng hợp ngẫu nhiên là họ đang ở trong các vị trí ngăn xếp chính xác mà printf yêu cầu họ phải làm gì đó với cách các chương trình 16 bit chạy trên Windows XP không? Một cái gì đó giống như một số bộ nhớ có lẽ là dành riêng để chạy một chương trình cụ thể? – SgrA

+0

@SgrA: Khá một vài ngôi sao phải căn chỉnh cho chương trình này hoạt động theo cách bạn mô tả. Nó sẽ là quá đơn giản để nói rằng đó là vì XP, hoặc bởi vì chương trình là 16-bit. – NPE

+0

Điều thú vị là nó đã hoạt động như mô tả ở trên mỗi lần duy nhất trong Turbo C++, nhưng không bao giờ ở bên ngoài nó, khiến tôi tò mò. – SgrA

4

Đây là số undefined behaviour. Vì vậy, nó có thể là bất cứ điều gì.

Cố gắng sử dụng

printf("%d %d%d", a,b,c) 

Lý do: - biến địa phương được gọi là trên stack và printf trong Turbo C++ thấy chúng theo thứ tự mà trong đó họ được chỉ định trong ngăn xếp.

GÓP Ý (Từ ý kiến): -

Hiểu lý do tại sao nó cư xử theo một cách đặc biệt với một trình biên dịch đặc biệt có thể hữu ích trong việc chẩn đoán các vấn đề, nhưng không thực hiện bất kỳ sử dụng khác của thông tin.

+0

Vâng, tôi tin rằng đầu ra có thể là bất cứ điều gì. Tôi muốn biết tại sao chính xác nó hoạt động trong Turbo C++. – SgrA

+0

NPE đã đưa ra lý do có thể là lý do tốt nhất !!! :) –

+0

@SgrA: - Cập nhật câu trả lời của tôi với lý do mặc dù NPE đã giải thích nó tốt hơn !!! :) –

4

Câu trả lời ở đây là chương trình có thể làm bất cứ điều gì - đây là hành vi không xác định. Theo tài liệu printf() s (tôi nhấn mạnh):

Theo mặc định, các đối số được sử dụng theo trình tự nhất định, trong đó mỗi '*' và mỗi chuyển đổi specifier yêu cầu đối số tiếp theo (và nó là một lỗi nếu không có đủ đối số).

Nếu kiểm tra trắc nghiệm của bạn không có lựa chọn cho "hành vi chưa xác định" thì đó là thử nghiệm không hoàn chỉnh. Dưới ảnh hưởng của hành vi không xác định, bất kỳ câu hỏi nào về câu hỏi kiểm tra trắc nghiệm như vậy là đúng về mặt kỹ thuật là.

3

Điều thực sự xảy ra là các đối số thường được chuyển vào ngăn xếp cuộc gọi. Các biến cục bộ là cũng được chuyển vào ngăn xếp cuộc gọi và do đó, printf() xem các giá trị đó, theo thứ tự nào mà trình biên dịch quyết định lưu trữ chúng ở đó.

Hành vi này, cũng như nhiều người khác, được phép dưới sự bảo trợ của behavoir không xác định

+0

Bạn có nghĩa là "biến cục bộ cũng được đặt trên ngăn xếp" thay vì "biến cục bộ cũng được chuyển vào ngăn xếp cuộc gọi" ... – Floris

2

Không, nó không liên quan đến kiến ​​trúc. Nó liên quan đến cách TurboC++ xử lý stack. Các biến số a, bc là những người dân địa phương và được phân bổ như vậy trong ngăn xếp. printf cũng hy vọng các giá trị trong ngăn xếp. Rõ ràng, TurboC++ không thêm bất kỳ thứ gì khác vào ngăn xếp sau khi người dân địa phương và printf có thể lấy chúng làm tham số. Chỉ là trùng hợp ngẫu nhiên.