2009-10-13 79 views
6
float b = 1.0f; 
int i = (int)b; 
int& j = (int&)b; 

cout << i << endl; 
cout << j << end; 

Gì Sau đó, đầu ra của i1, và đầu ra của 1065353216! Đó là một bất ngờ lớn đối với tôi! Vậy ý nghĩa thực sự của việc chuyển đổi (int&) là gì?ý nghĩa của (int &) chuyển đổi trong C++

Trả lời

18

Đây là vấn đề với dàn diễn viên kiểu C. Bạn phải nhìn kỹ để xem những gì bạn đang nhận được. Trong trường hợp của bạn "(int)" là một diễn viên tĩnh bình thường. Giá trị được chuyển thành int thông qua cắt ngắn. Trong trường hợp của bạn "(int &)" là diễn viên được diễn giải lại. Kết quả là một lvalue đề cập đến vị trí bộ nhớ của b nhưng được coi là một int. Nó thực sự là một sự vi phạm các quy tắc bí mật nghiêm ngặt. Vì vậy, đừng quá ngạc nhiên nếu mã của bạn không hoạt động nữa sau khi bật tất cả các tối ưu hóa.

đang tương đương với C++ phong cách phôi:

float b = 1.0f; 
int i = static_cast<int>(b); 
int& j = reinterpret_cast<int&>(b); 
cout<<i<<endl; 
cout<<j<<end; 

Kiểm tra yêu thích ++ cuốn sách C của bạn bằng các loại phôi.

+0

Vâng, Đó là một câu trả lời tuyệt vời. Nhưng tôi có thêm một câu hỏi nữa. Tại sao lỗi "lỗi: static_cast không hợp lệ từ loại‘ float ’để nhập‘ int & ’”, xảy ra khi tôi sử dụng static_cast để truyền float tới int & like "float b = 1.0f; int & j = static_cast b;". Tôi không tìm thấy những hạn chế của static_cast trong cuốn sách C++ ưa thích của tôi, "Ngôn ngữ lập trình C++". – toby

+3

Đó là sự bảo vệ bạn nhận được từ việc sử dụng phôi kiểu C++. Nếu trình biên dịch chấp nhận một cơ hội static_cast thì bạn không làm gì sai. Những thứ không an toàn duy nhất mà một diễn viên tĩnh cho phép bạn làm là chuyển đổi không được kiểm soát từ Base */Base & thành Derived */Derived & và void * thành T * theo như tôi có thể nhớ. Về cơ bản, nó có thể đảo ngược chuyển đổi tiềm ẩn, không nhiều hơn - không tính các chuyển đổi const. – sellibitze

+0

Xin chào, sellibitze, cảm ơn sự giúp đỡ của bạn! Tôi đạt được rồi! – toby

1

Có vẻ như bạn đang cố gắng tạo tham chiếu int cho một phao bằng cách sử dụng (int &) truyền. Điều đó sẽ không hoạt động vì các float được biểu diễn khác với int. Điều này sẽ không hoạt động.

Nếu đại diện của float và int giống nhau thì có thể nó đã hoạt động.

2
float b = 1.0f; 
... 
int& j = (int&)b; 

Trong chuyển đổi thứ hai, bạn đang xem không gian bộ nhớ có chứa b như thể đó là không gian bộ nhớ có chứa int. Giá trị dấu chấm động được lưu trữ theo cách hoàn toàn khác với số nguyên, do đó kết quả thực sự khác nhau ...

11

Trong hệ thập lục phân 1065353216 là 0x3F800000. Nếu bạn hiểu đó là số dấu phẩy động 32 bit bạn nhận được 1.0. Nếu bạn viết nó ra trong hệ nhị phân bạn có được điều này:

 
3 F 8 0 0 0 0 0 
0011 1111 1000 0000 0000 0000 0000 0000 

Hoặc nhóm khác nhau:

 
0 01111111 00000000000000000000000 
s eeeeeeee vvvvvvvvvvvvvvvvvvvvvvv 

Các bit đầu tiên (s) là bit dấu, 8 bit tiếp theo (e) là số mũ và 23 bit cuối cùng (v) là những điều có nghĩa. "Số mũ dấu chấm động nhị phân chính xác đơn được mã hóa bằng cách sử dụng biểu diễn nhị phân bù trừ, với chênh lệch bằng không là 127; còn được gọi là độ lệch số mũ trong IEEE 754 standard." Giải thích điều này bạn thấy rằng dấu là 0 (dương), số mũ là 0 (01111111 b = 127, "số không bù"), và mức độ là 0. Điều này cho bạn +0 là 1,0.

Nhưng dù sao, điều đang xảy ra là bạn đang tham chiếu đến một phao (b) và diễn giải lại nó dưới dạng tham chiếu int (int&). Vì vậy, khi bạn đọc giá trị của j bạn nhận được các bit từ b. Hiểu như là một phao những bit có nghĩa là 1.0, nhưng hiểu là một int những bit có nghĩa là 1065353216.

Đối với những gì nó có giá trị, tôi chưa bao giờ sử dụng một dàn diễn viên sử dụng & như (int&). Tôi sẽ không mong đợi để nhìn thấy điều này hoặc sử dụng điều này trong bất kỳ mã C + + bình thường.

+0

Này, có một lỗi đánh máy ở đây, (v) được lặp lại hai lần, sửa chữa đầu tiên (v) đến (e). – legends2k

+0

Tôi đọc mã lắp ráp được tạo bởi g ++. Đây là chính xác xảy ra trong chương trình. – toby

2

Trong trường hợp cụ thể này, chuyển đổi được đề cập không có ý nghĩa.Đó là một nỗ lực để giải thích lại bộ nhớ bị chiếm bởi một đối tượng float và một giá trị int. Điều này rõ ràng là bất hợp pháp trong C/C++, có nghĩa là nó tạo ra hành vi không xác định. Hành vi không xác định - đó là ý nghĩa duy nhất trong trường hợp này.

1

Bạn định làm gì? Điều tương tự:

float b = 1.0f; 
int i = (int) b; 
int* j = (int*)b;//here we treat b as a pointer to an integer 
cout<<i<<endl; 
cout<<(*j)<<endl; 

Cách khắc phục:

float b = 1.0f; 
int i = (int) b; 
int castedB = (int)b;//static_cast<int>(b); 
int& j = castedB; 
cout<<i<<endl; 
cout<<j<<endl; 
Các vấn đề liên quan