2015-12-15 14 views
9

Có hai có liên quan quy định tiêu chuẩn C:Chuyển đổi một con trỏ không `void` cho `uintptr_t` và ngược lại

chuẩn C99, 6.3.2.3:

Một con trỏ tới làm mất hiệu lực có thể được chuyển đổi sang hoặc từ một con trỏ đến bất kỳ loại không đầy đủ hoặc đối tượng nào. Một con trỏ tới bất kỳ kiểu đối tượng không đầy đủ hoặc đối tượng có thể được chuyển đổi thành một con trỏ để làm mất hiệu lực và ngược lại; kết quả sẽ là so sánh với con trỏ ban đầu.

7.20.1.4:

Các loại sau đây chỉ định một kiểu dữ liệu integer unsigned với tài sản mà bất kỳ con trỏ hợp lệ để làm mất hiệu lực có thể được chuyển đổi sang loại này, sau đó chuyển đổi trở lại con trỏ void, và kết quả sẽ so sánh bằng con trỏ gốc: uintptr_t

Điều đó có nghĩa, rằng followin mã g tuân thủ:

int *p = NULL; 
void *q = (void*)p; 
uintptr_t s = (uintptr_t)q; 

Nhưng nó thực sự cần diễn xuất hai bước? trình biên dịch sẽ thực hiện một diễn viên trung gian tiềm ẩn nếu làm một cái gì đó như:

int *p = NULL; 
uintptr_t s = (uintptr_t)p; 

(Vâng, nó có lẽ sẽ trên hầu hết các trình biên dịch, nhưng câu hỏi của tôi là về việc tuân thủ tiêu chuẩn)

+0

Lưu ý rằng 'p' không được khởi tạo trong cả hai. Có lẽ một cái gì đó như: 'int i = 42; int * p = & i; ... 'sẽ sửa chữa nó. –

+0

@ l3x, vâng, cảm ơn bạn. Vì lợi ích của sự hoàn chỉnh sẽ sửa chữa nó. –

Trả lời

7

tôi sẽ không có nguy cơ nó. Tiêu chuẩn làm cho nó rõ ràng rõ ràng những gì được cho phép và những gì không được phép.

Viết uintptr_t s = (uintptr_t)(void*)p; tín hiệu cho người đọc mã của bạn biết bạn đang làm gì.

+3

Thành thật mà nói, nếu tôi thấy mã đó, tôi sẽ hỏi liệu tác giả có biết họ đang làm gì không. Một phần bởi vì tôi sẽ không có một hồi ức đầy đủ về các đoạn có liên quan từ tiêu chuẩn trong tầm tay. Tôi không nói nó sai khi viết nó theo cách đó, nhưng nó sẽ không tấn công tôi như một cách rõ ràng. –

+2

Trong trường hợp đó, sẽ không có hại khi viết nhận xét. Phụ thuộc vào chính sách nhà của bạn. – Bathsheba

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