2012-06-12 42 views
13

Tôi đang làm việc bằng ngôn ngữ C và sửa đổi mã trước đó được viết bởi người khác. Tôi đang đấu tranh với một vài điều và tôi đang cố gắng hiểu càng nhiều càng tốt về những gì đang diễn ra như tôi có thể. Vì vậy, như câu hỏi của tôi đã nêu, sự khác biệt giữa static inline voidvoid khi tạo một hàm là gì? Tôi xin lỗi trước cho bài viết dài, nhưng tôi muốn bạn biết tôi đã làm một số nghiên cứu, nhưng không hiểu những gì tôi đã tìm thấy.Sự khác biệt giữa khoảng trống nội tuyến tĩnh và khoảng trống là gì?

tôi thấy an explanation of static gây bối rối cho tôi:

Từ khoá tĩnh nghĩa rằng chức năng không thể được tham chiếu từ các tập tin khác; nghĩa là tên không được xuất bởi người liên kết.

Bằng cách đọc này, tôi giả sử tham chiếu một hàm khác với gọi hàm? Tôi cho rằng vì hàm này được gọi từ một tệp .c khác. Nếu đó là trường hợp, những gì đang tham chiếu một chức năng?

Thông qua cùng một trang web, chúng giải thích inline functions và tôi không hiểu ý nghĩa của nó.

Từ khóa __inline yêu cầu trình biên dịch thay thế mã trong phạm vi định nghĩa hàm cho mọi trường hợp của cuộc gọi hàm. Tuy nhiên, thay thế chỉ xảy ra theo quyết định của trình biên dịch. Đối với ví dụ , trình biên dịch không inline một hàm nếu địa chỉ của nó là được thực hiện hoặc nếu nó quá lớn để nội tuyến.

Huh ???

Bất kỳ trợ giúp nào được đánh giá cao và tôi một lần nữa xin lỗi vì bài đăng dài khủng khiếp.

Sau đây tọa lạc tại file1.c (Sử dụng tên chung như tôi không nghĩ rằng nó quan trọng)

COMPLEX cNoiseSample; 
CGauss(&cNoiseSample, loopbackRadio->pState); 

Sau đây tọa lạc tại file2.c

static inline void CGauss(COMPLEX * pcGauss, P_OS_UNIFORM_RAND_STATE pState) 
{ 
    //code 
} 

Trả lời

12

static có nghĩa là không thể tham chiếu từ đơn vị biên dịch khác (tệp nguồn). "Được tham chiếu" có nghĩa là được gọi hoặc được gọi theo tên, ví dụ: được gán cho một con trỏ hàm.

inline là gợi ý cho trình biên dịch rằng mã của hàm sẽ được tạo nội dòng tại vị trí được gọi, thay vì được tạo dưới dạng hàm riêng biệt được phân nhánh thành. Điều này thường được thực hiện vì lý do hiệu suất. Để đối phó với báo giá của Microsoft:

trình biên dịch không inline một hàm nếu địa chỉ của nó được lấy hoặc nếu nó là quá lớn để nội tuyến.

Chức năng nội tuyến không có địa chỉ vì nó không tồn tại dưới dạng thực thể riêng biệt. Mã của nó chỉ đan xen liền mạch với mã mà nó được gọi. Vì vậy, nếu bạn lấy địa chỉ của một hàm (ví dụ: để gán cho một con trỏ) thì trình biên dịch phải tạo ra nó như là một hàm thực và không thể nội tuyến nó.

void có nghĩa là hàm không trả về giá trị.


Sau khi xem xét mẫu mã của bạn, tôi đoán rằng có một nét riêng biệt của CGauss() nơi nào đó, mà đã được gọi từ file1.c, trong khi file2.c đang kêu gọi riêng của nó phiên bản. Hoặc là, hoặc tệp1.c#include ing file2.c. Mà sẽ là khó chịu.

+0

Ngoài ra, 'inline' là cần thiết để thực thi quy tắc một định nghĩa khi hàm được xác định trong tiêu đề được bao gồm trong các đơn vị biên dịch khác nhau (hoặc ít nhất đây là trường hợp cho C++, không biết chi tiết này chính xác trong C, I tưởng tượng nó sẽ giống nhau) – rubenvb

+0

Tôi đoán tôi hơi bối rối hơn @ Graham-Borland. Để tôi cho bạn thấy lý do: COMPLEX cNoiseSample; CGauss (& cNoiseSample, loopbackRadio-> pState);/* Mã này được gọi tại một điểm trong tệp nguồn .c và trong tệp nguồn .c khác tôi có: */static inline void CGauss (COMPLEX * pcGauss, P_OS_UNIFORM_RAND_STATE pState)/* Tôi xin lỗi vì định dạng kém trong hộp nhận xét, không chắc chắn cách thực hiện việc này. */ – TZPike05

+0

Chỉnh sửa câu hỏi của bạn, dán đoạn mã đó vào đó. –

6

static chỉ có nghĩa là khi bạn có nhiều tệp nguồn. Nó chỉ định rằng không thể truy cập chức năng hoặc biến số static từ các hàm trong một tệp khác.

inline là trình tối ưu hóa trình biên dịch giúp tăng tốc mã của bạn trong một số trường hợp nhất định. Bất cứ khi nào bạn gọi một hàm, có một số chi phí liên quan đến nó. Vì vậy, những gì trình biên dịch có thể làm là loại bỏ chức năng tất cả cùng nhau bằng cách sao chép + dán (gần như) mã nội tuyến.

Dưới đây là một ví dụ về nội tuyến:

int dotproduct(int x1, int y1, int x2, int y2) { 
    return multiply(x1,x2)+multiply(y1,y2); 
} 

inline int multiply(int a, int b) { 
    return a*b; 
} 

Trình biên dịch sẽ tắt chức năng này vào:

int dotproduct(int x1, int y1, int x2, int y2) { 
    return x1*x2+y1*y2; 
} 

Nếu bạn muốn trở thành ưa thích, bạn cũng có thể nội tuyến chức năng dotproduct;)

Lưu ý rằng từ khóa inline chỉ đơn giản là một cú huých đến trình biên dịch để nội tuyến một số chức năng nhất định. Nó có thể hoặc có thể không thực sự làm điều đó tùy thuộc vào bản án riêng của nó.

+0

Thanks @tskuzzy, nội tuyến có ý nghĩa hơn bây giờ. – TZPike05

0

tĩnh chỉ có nghĩa là về cơ bản các chức năng là cho tất cả các tính năng 'vô hình' bên ngoài của tập tin nguồn mà nó được định nghĩa trong.

inline askes trình biên dịch để cơ bản substite mã chức năng cuộc gọi trực tiếp vào nguồn tại mỗi vị trí hàm được gọi tại thời gian biên dịch (như thay thế hàm gọi bằng mã của hàm) - tuy nhiên, nó không được đảm bảo xảy ra, nó chỉ gợi ý nó cho trình biên dịch của bạn.

Đó là kỹ thuật hơn thế và bạn có khả năng nhận được câu trả lời tốt hơn nhiều, nhưng bằng ngôn ngữ đơn giản, đây là ý nghĩa của thuật ngữ.

2

Các tĩnh từ khóa

Định nghĩa một hàm C có nghĩa là tĩnh (như các tài liệu nói) rằng chức năng này chỉ có thể được truy cập từ các nguồn tập tin nó được định nghĩa trong. Thuật ngữ "tài liệu tham khảo trong sence này phương tiện hoặc gọi hàm này hoặc lấy một con trỏ hàm tới nó.

nội tuyến

Thông thường, khi bạn viết một hàm trong C, trình biên dịch tạo ra mã máy cho chức năng này:

foo: 
    /* some machine code */ 
    ret 

Mỗi lần bạn gọi chức năng này, trình biên dịch chèn một lệnh chẳng hạn như

call <foo> 

vào mã máy của người gọi, có nghĩa là không có gì khác hơn là "chuyển sang foo, e xecute những gì bạn tìm thấy ở đó và khi bạn gặp phải một hướng dẫn ret, quay trở lại vị trí này. "

Ngược lại, đối với các hàm nội tuyến, trình biên dịch không tạo ra hàm foo() riêng biệt, mà thay vào đó chèn mã máy cho hàm foo vào mọi trang gọi. Khi thực thi mã này, điều này có cùng tác dụng.

Vậy tại sao chúng ta làm điều đó? Mã nội tuyến có lợi thế là giúp bạn tiết kiệm hai lần nhảy (cuộc gọi và lần truy cập tương ứng), điều này làm cho mã của bạn thực thi nhanh hơn một chút. Nhược điểm, mã của bạn trở nên lớn hơn, bởi vì bạn chèn mã máy trên mọi trang cuộc gọi thay vì chỉ có một bản sao của một hàm có thể gọi. Đó là lý do tại sao bạn thường chỉ nội tuyến các chức năng nhỏ.

Ngoài ra, bạn không thể đưa con trỏ hàm vào các hàm nội dòng và gỡ lỗi trở nên khó khăn hơn, vì bạn không thể đặt điểm ngắt trên hàm nội dòng dễ dàng.

Do đó, nội tuyến còn lại cho trình biên dịch như một tùy chọn tối ưu hóa và bằng cách sử dụng một từ khóa như inline C++ 's, chỉ thị nội tuyến của bạn, hoặc của GCC __attribute ((inline)), bạn chỉ cung cấp cho các trình biên dịch một gợi ý rằng nội tuyến có thể đáng để thử ở đây.

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