2010-04-29 56 views
11

Tôi đã tham dự một cuộc phỏng vấn kỹ thuật cách đây vài ngày, và tôi đã được hỏi Trình biên dịch C hàm hoạt động như thế nào với số biến đối số? Làm cách nào để vượt qua ngăn xếp?Trình biên dịch C thực hiện các hàm với các số biến số của các đối số như thế nào?

Có ai biết hoặc có thể khám phá điều đó không?

Cảm ơn, Dan

+1

Theo như tôi biết, các hàm varargs phụ thuộc vào việc triển khai thực hiện. – WhirlWind

Trả lời

10

Theo như tôi biết, với C ...

  • chức năng gọi đẩy đối số vào stack theo thứ tự từ phải sang trái.

  • người gọi chịu trách nhiệm xóa các đối số khỏi ngăn xếp sau khi hàm được gọi đã được thực thi. Điều này có lẽ chính xác bởi vì người gọi được đảm bảo để biết có bao nhiêu đối số được đặt trên ngăn xếp, trong khi hàm được gọi có thể làm cho nó sai.


P.S .:ước Calling thường thực hiện cụ thể. Những gì tôi vừa mô tả được gọi là quy ước gọi là "cdecl". Ngược lại điều này với một quy ước gọi thường được gọi là "stdcall", trong đó hàm được gọi có trách nhiệm loại bỏ các đối số của nó khỏi ngăn xếp. Do đó, nó không hỗ trợ các danh sách đối số có độ dài thay đổi.


P.P.S .: Như dùng nategoose nhận xét, tôi không đề cập đến cách biến danh sách đối số thực sự sử dụng. Xem ví dụ số POSIX documentation for the <stdarg.h> header để biết thêm thông tin.

+2

Điều này rất rõ ràng, nhưng bạn đã bỏ qua vai trò của callee. Các callee (chẳng hạn như printf) phải sử dụng một hoặc nhiều đối số bắt buộc (như chuỗi định dạng) để biết các tham số trên ngăn xếp sẽ là gì.Sau đó nó sử dụng các macro mục tiêu cụ thể để truy cập các macro đó (một chồng hệ thống là một mảng có đầu bạn có thể di chuyển). Tiêu đề stdarg.h chứa các macro bạn cần thực hiện điều này, và thường là một con trỏ tới đầu của mảng này được chuyển đến một hàm mà dự kiến ​​sẽ làm việc trên đó (như vprintf). – nategoose

+0

@nategoose: Cảm ơn bạn đã bổ sung có giá trị của bạn. Chỉ cần để cho bạn biết, tôi ban đầu rời khỏi mục đích này, vì OP hỏi làm thế nào trình biên dịch * thực hiện các danh sách đối số biến, chứ không phải cách lập trình * thực sự sử dụng chúng. Tôi đã thêm siêu liên kết vào tài liệu tham chiếu ngay bây giờ. – stakx

7

Nó thực hiện chúng bằng cách sử dụng các macro va_ - ví dụ va_start. Chính xác những gì các macro này thực hiện được xác định - nói cách khác nó sẽ thay đổi từ kiến ​​trúc CPU đến kiến ​​trúc, và từ trình biên dịch sang trình biên dịch. Nhưng họ phải chơi thủ đoạn với ngăn xếp cuộc gọi C. Thông thường, điều này sẽ liên quan đến việc lấy địa chỉ của tham số được đặt tên cuối cùng làm cơ sở, và sau đó truy cập các tham số variadic bằng cách thực hiện số học con trỏ trên cơ sở này.

+0

Yup, tôi nhớ đó là lý do tại sao bạn luôn cần một tham số được đặt tên trước ... – dicroce

-1

Nhìn vào va_start, va_arg và va_end. Here là một tấn thông tin về điều này.

0

Như xa, như bạn buồn mà bạn nhận được câu hỏi này trên cuộc phỏng vấn công nghệ, tôi sẽ giả định rằng câu trả lời đúng sẽ là:

Caller sẽ đẩy các thông số rõ ràng để ngăn xếp, đếm các tham số biến và các tham số biến chinh no. Sau đó, mã chức năng đích sẽ chịu trách nhiệm pop-ing tất cả các tham số dựa trên số lượng đã qua và địa chỉ ngăn xếp của nó.

Và thêm một số ý tưởng, tại sao việc đặt tham số này trong mảng riêng biệt không thuận tiện.

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