2010-08-31 32 views
15

Các vĩ mô được định nghĩa là:Tại sao MAKEINTRESOURCE() hoạt động?

#define MAKEINTRESOURCEA(i) ((LPSTR)((ULONG_PTR)((WORD)(i)))) 
#define MAKEINTRESOURCEW(i) ((LPWSTR)((ULONG_PTR)((WORD)(i)))) 

Tại sao điều này có thể được sử dụng để chỉ hoặc là một ID tài nguyên (16-bit unsigned int) hoặc tên của nó (một con trỏ đến một mảng của char)? Điều này không giới hạn hiệu quả không gian địa chỉ (trên hệ thống 32 bit) đến 16-bit? Nếu không, hệ thống sẽ biết tôi có đang sử dụng ID hay tên không?

+2

Các macro này luôn làm tôi bối rối. Tại sao họ không chỉ thực hiện hai chức năng riêng biệt, một trong đó có một số nguyên ID và một trong đó có một chuỗi ... – dreamlax

+0

cảm ơn đây thực sự là những gì tôi đang tìm kiếm. –

+0

@dreamlax: Không làm điều đó thực sự giải quyết một trong những vấn đề nó đã được tạo ra ở nơi đầu tiên;) Tất cả dữ liệu và chức năng trong một DLL được gán một thứ tự, và thứ tự có thể được sử dụng thay cho tên nếu bạn muốn. Điều này áp đặt một giới hạn về số lượng các phần tử có thể sử dụng trong một DLL đến 65K (do, trớ trêu thay, với sự tồn tại của macro này và cách nó tương tác với 'GetProcAddress'). Nếu bạn muốn duy trì khả năng tương thích ABI giữa các phiên bản DLL bằng cách có nhiều phiên bản của các hàm, mỗi phiên bản với các số thứ tự duy nhất, thì càng ít chức năng bạn có thể làm cho mọi thứ trở nên tốt hơn. –

Trả lời

18

Điều này hoạt động vì Windows không cho phép các trang ánh xạ cho 64 KB đầu tiên của không gian địa chỉ. Để bắt các tham chiếu con trỏ null. Nhưng tôi cũng nghĩ rằng để bắt lỗi con trỏ trong các chương trình đã được chuyển đổi từ phiên bản Windows 16 bit.

Tác dụng phụ là điều này cho phép phân biệt đáng tin cậy ID tài nguyên được đóng gói thành giá trị con trỏ vì chúng luôn trỏ đến bộ nhớ không thể chuyển đổi.

+0

+1 cho lịch sử. Nó chắc chắn có vẻ giống như một lý do chính đáng cho sự hạn chế đó trên con trỏ. – RBerteig

4

Có, nó giới hạn không gian địa chỉ, nhưng không nhiều như bạn nghĩ. Họ đã khắc phục được 64KB không gian địa chỉ 4GB của bạn một cách hiệu quả. Hầu hết, nếu không phải tất cả, 64KB đó đã được dành riêng cho những thứ khác trên Windows, do đó mất hiệu quả là không có gì.

Nhìn chung, đó là một khoản tiết kiệm không gian, vì chúng không cần thêm một chút thông tin để phân biệt giữa một con trỏ và một số nguyên ID. Điều này đã được phát minh trở lại trong những ngày tuổi tồi tệ, khi không gian ở mức cao.

+0

Cảm ơn bạn đã trả lời. Nhưng tôi không hiểu tại sao nó chỉ mất 64KB. ID giao dịch là trình kết nối 16 bit và con trỏ dài 32 bit. Nó sẽ không làm giảm không gian địa chỉ của một con trỏ đến 16-bit dài? – user418680

+1

Nếu giá trị nhỏ hơn 64KB, nó được giả định là một số nguyên ID. Nếu nó lớn hơn 64KB (tất cả các con đường lên đến 4GB), thì nó được giả định là một con trỏ. –

+0

Hãy nhớ rằng, bạn không chuyển tên tài nguyên chuỗi thông qua macro này, chỉ có một ID tài nguyên số nguyên. Nó hạn chế các ID tài nguyên số nguyên đến 16 bit, nhưng IIRC chúng đã được định dạng tài nguyên nhị phân. – RBerteig

13

Macro MAKEINTRESOURCE chỉ thực hiện truyền giữa tham số số và con trỏ chuỗi. Con trỏ chuỗi kết quả là không hợp lệ và không thể được dereferenced như tên tài nguyên. Tuy nhiên, API xử lý tài nguyên phát hiện các con trỏ như vậy theo giá trị tuyệt đối của chúng và coi chúng là ID tài nguyên chứ không phải tên tài nguyên. Kể từ C-style API không hỗ trợ quá tải, họ không thể xác định hai chức năng như:

 
HICON LoadIcon(HINSTANCE hInstance,LPCTSTR lpIconName); 
HICON LoadIcon(HINSTANCE hInstance,UINT resourceId); 

Vì vậy, các nhà phát triển API quyết định sử dụng các chức năng tương tự cho cả hai trường hợp, cung cấp MAKEINTRESOURCE vĩ mô cho người sử dụng API. Tôi tin rằng hai chức năng khác nhau có thể trông đẹp hơn:

 
HICON LoadIconByName(HINSTANCE hInstance,LPCTSTR lpIconName); 
HICON LoadIconById(HINSTANCE hInstance,UINT resourceId); 

Nhưng đây không phải là cách Windows API được triển khai. ID tài nguyên hợp lệ luôn nhỏ hơn giá trị con trỏ có thể tối thiểu. Tham số tên tài nguyên được chuyển tới API mà không có macro này và giá trị của nó không bị hạn chế.

+0

đây là một câu trả lời tuyệt vời –

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