2012-11-14 43 views
13

thể trùng lặp:
Inline functions vs Preprocessor macroschức năng inline vs chức năng vĩ mô

Tôi muốn biết sự khác biệt giữa các chức năng nội tuyến và chức năng vĩ mô.

1) là hàm nội tuyến có giống với hàm macro không?

2) Tôi biết rằng cả hai đều không được gọi nhưng chúng được thay thế bằng mã của nó trong giai đoạn biên dịch. không phải là?

3) Nếu có sự khác biệt, Bạn có thể chỉ định không?

+0

http://msdn.microsoft.com/en-us/library/bf6bf4cf.aspx – CCoder

Trả lời

22

Nội tuyến thay thế cuộc gọi đến hàm có nội dung của hàm, tuy nhiên, nội tuyến chỉ là yêu cầu cho trình biên dịch có thể bỏ qua (bạn vẫn có thể chuyển một số cờ tới trình biên dịch để buộc nội tuyến hoặc sử dụng always_inline thuộc tính với gcc).

Một macro, mặt khác, được mở rộng bởi preprocessor trước khi biên dịch, do đó, nó giống như thay thế văn bản, cũng macro không phải là loại kiểm tra, chức năng nội tuyến được. Có so sánh trong số wiki.

Vì lợi ích của sự hoàn chỉnh, bạn vẫn có thể có một số loại loại an toàn với các macro, sử dụng gcc của __typeof__ ví dụ, sau đây tạo ra mã gần như giống hệt nhau và cả hai nguyên nhân cảnh báo nếu sử dụng với các loại sai:

#define max(a,b) \ 
    ({ __typeof__ (a) _a = (a); \ 
     __typeof__ (b) _b = (b); \ 
    _a > _b ? _a : _b; }) 

__attribute__((always_inline)) int max(int a, int b) { 
    return (a > b ? a : b); 
} 

Lưu ý: đôi khi các macro không kiểu chữ chỉ là những gì cần thiết, ví dụ, hãy xem cách uthash sử dụng các macro để làm cho bất kỳ cấu trúc C có thể băm nào mà không cần đến phôi.

1

Không inline không giống như định nghĩa macro, vì macro được xử lý trước nhưng nội tuyến chỉ là chỉ báo cho trình biên dịch để đặt toàn bộ phần thân của hàm mà nó được gọi.

đặt từ khoá inline trước khi bất kỳ định nghĩa hàm chỉ là dấu hiệu cho thấy hoặc yêu cầu, trình biên dịch là miễn phí để lựa chọn cho dù nó sẽ làm cho điều đó hàm nội tuyến hoặc để lại nó như bình thường

thay vĩ mô: preprocessing phase (tức là trước khi biên dịch)

- tập tin đầu vào tập tin test.c kết quả trong linux test.i

thay inline: compilation phase

6

Macro là các khai báo được thay thế bởi bộ tiền xử lý (trước khi thực hiện biên dịch) Các chức năng này không có chức năng gì cả. Trước khi thực tế biên dịch giai đoạn bắt đầu các macro đã biến mất, và tất cả những gì còn lại là mở rộng của chúng (bao gồm mở rộng thành không có gì).

Các chức năng nội dòng, trên thực tế, các chức năng tuân thủ theo ngôn ngữ, với các quy tắc phạm vi, khai báo biến, cấu trúc logic (vòng lặp, v.v.), v.v.Một hàm nội tuyến không được mở rộng bước biên dịch trước như macro. Chúng được biên dịch giống như mã thông thường, nhưng sau đó có thể được tiêm (vì thiếu thuật ngữ tốt hơn) vào mã được biên dịch và được tối ưu hóa khi cần.

+0

bạn vẫn có thể có phạm vi {}, khai báo và vòng lặp với macro – iabdalkader

+0

@mux có ai đó đang chiếm đoạt ngôn ngữ tiền xử lý (đó là tất cả macro là) ​​trong khi tôi không tìm kiếm? Tôi đã không nhìn thấy một vòng điều khiển được xác định trong (và do đó thay thế ra sau khi tiền xử lý) C/C + + macro, nhưng tôi chắc chắn quan tâm đến thấy một ví dụ. Bạn chắc chắn có thể có phạm vi '{...}' trong bất kỳ macro nào ** phát ra ** trong giai đoạn xử lý tiền xử lý, nhưng nếu có cách để thực hiện '#for i = 0' hoặc' #while (true) 'xây dựng trong macro tiền xử lý, tôi chưa bao giờ thấy nó (nhưng một lần nữa, sẽ quan tâm đến việc xem ví dụ của bạn). – WhozCraig

+0

có xem mã nguồn của [uthash] (http://www.codeforge.com/read/104731/uthash.h__html) một bảng băm (và danh sách liên kết) được viết hoàn toàn bằng các macro :) – iabdalkader

17

1) Số

2) Một Macro trong C chỉ đơn giản là văn bản được mở rộng trước trình biên dịch xử lý mã nguồn. Từ khóa nội tuyến được sử dụng như một gợi ý cho trình biên dịch rằng hàm có thể được đặt nội tuyến mà không cần một ngăn xếp cuộc gọi được thiết lập.

Vì vậy, ví dụ, cho phép nói rằng bạn có hai đoạn mã sau (First vĩ mô và sau đó là chức năng inline):

#define MAX(x,y)  (x > y ? x : y) 

inline int max(int x, int y) { return x > y ? x : y; } 

Khi preprocessor tìm thấy cuộc gọi sau trong mã của bạn:

int highest = MAX (var_1, var_2); 

nó sẽ thay thế bằng

int highest = (var_1 > var_2 ? var_1 : var_2); 

Trên đây là những gì các trình biên dịch cuối cùng được trong quá trình biên soạn, vì thế đoạn xác định bởi MAX (x, y) là thay cho MAX (VAR_1, VAR_2). Khi trình biên dịch tìm thấy hàm gọi

int highest = max (var_1, var_2); 

Sau đó, hàm "max" được gọi. Bạn phải giả định rằng nó được gọi là cách bình thường, bởi vì trình biên dịch được tự do bỏ qua gợi ý "nội tuyến" của bạn và thực hiện cuộc gọi đến hàm thông qua lệnh gọi bình thường thay vì chỉ đặt mã cho hàm ở vị trí của nó đã gặp.

Một caveat cuối cùng với các macro: vì nó là tất cả thay thế văn bản và không mã thay thế, nếu bạn làm điều gì đó như thế này:

int highest = MAX (v1++, v2++); 

Preprocessor sẽ mở rộng đến:

int highest = (v1++ > v2++ ? v1++ : v2++); 

mà có lẽ không phải là những gì bạn dự định.

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