Void * a = & a hợp pháp như thế nào?


88

Hãy xem xét mã C ++ sau:

void* a = &a;

Tại sao trình biên dịch không phàn nàn về việc sử dụng số nhận dạng không được khai báo?

Ngoài ra, trình biên dịch coi biến alà gì? Nó là một con trỏ tới một đối tượng void hay là một con trỏ tới một void*con trỏ?




15
Nên đề cập đến lý do tại sao bạn muốn làm điều này - để đưa một con trỏ đến đầu ngăn xếp (từ đó bạn có thể thao tác với mọi thứ).
OrangeDog

Câu trả lời:


95

Phạm vi khai báo các biến trong C ++ có thể khá đáng ngạc nhiên:

void* a =               &a;
         ^~~~~~~~~~~~~~~~~
          a declared as `void*` from here on

Vì vậy, &avoid**nhưng vì bất kỳ loại con trỏ là mặc nhiên chuyển đổi thành void*...


Làm cách nào để gán một đối tượng hữu ích cho cái này?
user2681063

22
@ user2681063 a = &userfulObject?
Nikos C.

4
@MarkGarcia: Lưu ý rằng đó void *a = a;sẽ là UB nếu được khai báo cục bộ, nếu không thì ở phạm vi không gian tên cũng tốt.
Nawaz

1
@TheodorosChatzigiannakis: Tôi tin là có.
Matthieu M.

1
Một trích dẫn đặc tả sẽ thực sự tốt ở đây.
Benjamin Gruenbaum

30

Nó tương đương với

void* a;
a = &a;

Do đó, ađã được khai báo. Vì vậy, anhận được địa chỉ của avăn bản a. Vì vậy, nó là một con trỏ tới một con trỏ void. (Bạn chưa xác định bất kỳ đối tượng nào.)


9
Về mặt kỹ thuật, bạn đã xác định một đối tượng. achính nó là một đối tượng. (Không phải tất cả các đối tượng có kiểu do người dùng định nghĩa trong C ++)
MSalters

1
@MSalters bạn nói về 'đối tượng' này là gì? : D
Gusdor

3
@Gusdor Chúng ta chỉ có thể giả định những gì nằm ngoài khoảng trống của chân trời sự kiện.
Cole Johnson

Chúng được gọi khác nhau, tuy nhiên "hiệu ứng" là giống nhau trong trường hợp này
Stasik

Nhìn chung, chúng không tương đương nhau, nhưng trong trường hợp này thì chúng đúng như vậy.
Các cuộc đua ánh sáng trong quỹ đạo vào

7

Trong void* a, ađược khai báo là một con trỏ không phải đến một voidkiểu mà là "bất kỳ" kiểu nào (trường hợp đặc biệt). Tất nhiên, một địa chỉ (vị trí trong bộ nhớ) được gán acho bất kỳ biến nào khác đang được khai báo.

Sau đó, biểu thức &ađược đánh giá để khởi tạo biến (cũng được a, nhưng điều này không liên quan) vừa được khai báo. Loại &alà "con trỏ tới con trỏ đến bất kỳ loại nào", là một trường hợp đặc biệt của "con trỏ tới bất kỳ loại nào", hoàn toàn tương thích với loạia . Ergo, không có thông báo trình biên dịch.

Hệ quả: không sử dụng void*nếu bạn muốn kiểm tra kiểu mạnh. Bất cứ điều gì có thể được chuyển đổi sang nó. Chỉ ngược lại theo hướng ngược lại, ngoại trừ void*chính nó (sẽ là một ngoại lệ không cần thiết khi một loại không tương thích với chính nó).

Ngoài ra, AFAIR điều này thực sự đến từ C.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.