2010-08-25 38 views
6

Đây là mã tôi có:Câu hỏi liên quan đến "C4312 cảnh báo: 'loại dàn diễn viên"

HWND WebformCreate(HWND hParent, UINT id) 
{ 
    return CreateWindowEx(0, WEBFORM_CLASS, _T("about:blank"), 
     WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE, 0, 0, 100, 100, hParent, 
     (HMENU)id, GetModuleHandle(NULL), 0); 
} 

Đây là cảnh báo tôi nhận được:

warning C4312: 'type cast' : conversion from 'UINT' to 'HMENU' of greater size 

Đây là những câu hỏi tôi có:

  1. Tại sao trình biên dịch nghĩ rằng ý tưởng tồi là truyền sang loại lớn hơn?
  2. Cách tốt nhất để loại bỏ cảnh báo là gì? (Tôi không muốn vô hiệu hóa nó.)
  3. Làm một loại hai diễn viên như thế này: (HMENU)(UINT_PTR)id sẽ loại bỏ cảnh báo. Sao lại như vậy?
  4. Tắt "Phát hiện vấn đề về khả năng di chuyển 64 bit" (Wp64) cũng sẽ loại bỏ cảnh báo. Tại sao Wp64 không được dùng nữa? Tôi có nên dùng nó không?

Trả lời

2

Bạn đang truyền Url 32 bit tới con trỏ 64 bit. Đó là tự tử - bạn đang cố gắng chỉ vào một cái gì đó nhưng quên một nửa vị trí của nó! Bạn hoàn toàn PHẢI mất một UINT_PTR. Khi bạn đưa con trỏ tới một int, hành vi này chỉ OK nếu int có cùng kích thước với con trỏ. Khác, đó là kết thúc thời gian chạy của ứng dụng của bạn miễn là vi phạm quyền truy cập.

Chỉnh sửa:
Tại sao trình biên dịch nghĩ rằng ý tưởng tồi là truyền sang loại lớn hơn?
R.E. trên

Cách tốt nhất để loại bỏ cảnh báo là gì? (Tôi không muốn vô hiệu hóa nó.)
Khắc phục sự cố. Mã này sẽ gần như chắc chắn instacrash.

Thực hiện loại dàn diễn viên kép như sau: (HMENU) (UINT_PTR) id sẽ loại bỏ cảnh báo. Sao lại như vậy?
Điều này xảy ra vì việc truyền UINT đến UINT_PTR hoàn toàn hợp lệ - UINT_PTR chỉ là một loại không thể thiếu, không mất dữ liệu.

Tắt "Phát hiện vấn đề về khả năng di chuyển 64 bit" (Wp64) cũng sẽ loại bỏ cảnh báo. Tại sao Wp64 không được dùng nữa? Tôi có nên dùng nó không?
Nó không được chấp nhận bởi vì, trên thực tế, tôi không thể nhớ tại sao. Tôi nghĩ rằng nó cảnh báo một chút quá dễ dàng. Nhưng đối với các cơ bản "Đừng đúc các loại tích phân và con trỏ", bạn chắc chắn nên để nó trên.

+0

Tôi không hiểu. Bạn có thể mở rộng câu trả lời này không? Tôi không giao dịch với con trỏ ở đây. Nó chỉ là một id điều khiển. – Tobbe

+0

HMENU là một Xử lý cho một Menu, đó là một con trỏ. typedef HMENU__ * HMENU là định nghĩa của HMENU. – Puppy

+1

Mã hoạt động tốt như hiện tại. Không có sự cố. Sao chép/dán từ msdn: "Đối với cửa sổ con, hMenu chỉ định mã định danh cửa sổ con, giá trị số nguyên được sử dụng bởi điều khiển hộp thoại để thông báo cho phụ huynh về sự kiện." – Tobbe

10

Loại ẩn đằng sau tên HMENU thực tế là kiểu con trỏ . Trình biên dịch cho bạn biết rằng một số số nhỏ hơn cho con số lớn hơn không có ý nghĩa, vì giá trị con trỏ kết quả sẽ "không đầy đủ", tức là các bit thứ tự cao hơn nếu giá trị con trỏ sẽ được điền bằng số không. Sau này làm cho rất ít ý nghĩa với các loại con trỏ.

Trong trường hợp cụ thể của bạn, điều này là an toàn, vì giá trị HMENU này thực sự không phải là con trỏ trỏ đến bất kỳ đâu. Tuy nhiên, trình biên dịch không biết rằng, đó là lý do tại sao nó đưa ra cảnh báo. Sử dụng loại số lớn hơn làm loại trung gian trong dàn diễn viên và cảnh báo sẽ biến mất (bạn tự đề xuất), vì trong trường hợp này bạn đang thực hiện hai phôi: số nguyên nhỏ hơn cho số nguyên lớn hơn và sau đó là số nguyên lớn hơn con trỏ.Số nguyên nhỏ hơn cho một số nguyên lớn hơn là một số số học, mà nó làm cho cảm giác hoàn hảo để điền vào các bit bậc cao hơn với số không (giá trị đại diện không thay đổi), do đó sẽ không có cảnh báo cho nó.

+1

Cảm ơn lời giải thích tuyệt vời về lý do tại sao diễn viên lồng đôi hoạt động! – Tobbe

2

Tại sao trình biên dịch nghĩ ý tưởng tồi là truyền sang loại lớn hơn?

Việc truyền giữa các loại kích thước khác nhau thường là một vấn đề có vấn đề, vì loại nguồn có thể không thể đại diện cho tất cả các giá trị cần thiết cho mục tiêu.

Cách tốt nhất để loại bỏ cảnh báo là gì? (Tôi không muốn vô hiệu hóa nó.)

Tôi muốn nói, sử dụng HMENU ở khắp mọi nơi và tuyên bố chức năng của bạn như

HWND WebformCreate(HWND hParent, HMENU id) 

Làm một loại diễn viên đôi như thế này: (hMenu) (UINT_PTR) id sẽ loại bỏ cảnh báo. Sao lại như vậy?

UINT_PTR là một loại số nguyên đủ lớn để giữ tất cả các giá trị con trỏ, do đó cảnh báo biến mất.

HMENU là loại con trỏ. Điều này không có nghĩa là một giá trị của một hMenu thực sự là một con trỏ, nhưng đây là một hack mà không cho phép bạn trộn hoàn toàn ví dụ. HMENUHWND (vì HMENUHWND tương tự như struct _hMENU*struct _hWND*, không tương thích, trong khi UINT s sẽ là).

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