2013-08-16 43 views
8

tôi có:chuyển đổi int để ngắn trong C

int a = 2147483647; 
short b = (short)a; 

và tôi nhận được b = -1 trong khi tôi mong đợi int32 được chuyển đổi sang int16 (short). Tôi hy vọng sẽ thấy một số giá trị và không phải-1.

Vui lòng ai đó giúp tôi với điều này.

+1

Tôi muốn nói, giá trị không phù hợp, vì vậy kết quả không xác định. –

+2

'-1' * là *" một số giá trị ". Và diễn viên '(ngắn) 'là không cần thiết; chuyển đổi sẽ được thực hiện hoàn toàn: 'short b = a;' –

+2

@BartFriederichs: Kết quả của việc chuyển đổi là * thực hiện xác định *, không được xác định. –

Trả lời

3

int A của bạn lớn hơn kích thước ngắn. Khi bạn chuyển đổi A thành ngắn, bạn nhận được 1 ở bên trái nhiều nhất, điều này sẽ cho biết rằng đó là số âm. Kể từ khi bạn nhận được -1, tôi cho rằng bạn đang nhận được 1s trong tất cả 16 bit, đó là sẽ cung cấp cho bạn -2^15 + 2^14 + 2^13 ... + 2^0, mà sẽ cung cấp cho bạn -1. Trong ngắn hạn (không có ý định chơi chữ), bạn không thể chuyển đổi số nguyên thành ngắn nếu nó quá lớn.

17

Giá trị 2147483647 hoặc 2 -1 tràn số nguyên 16 bit. Biểu diễn nhị phân của nó bằng 0 trong MSB, tiếp theo là 31 trong các bit còn lại.

Dường như trong quá trình triển khai của bạn, 16 bit cuối cùng được thực hiện trong chuyển đổi thành short. Khi điều này xảy ra, tất cả chúng được thiết lập để 1, dẫn đến một đại diện 2's complement của -1:

32-bit int: 01111111111111111111111111111111 
16-bit short: ----------------1111111111111111 

Tuy nhiên, không phải đại diện 2 lời khen cũng không hành vi này nói chung là một phần của chuẩn C++, vì vậy hành vi này được xác định thực hiện.

+7

@EricPostpischil: Hành vi không được xác định; kết quả được xác định thực hiện, có nghĩa là việc thực hiện phải ghi lại nó. –

+2

@EricPostpischil: n3690 trang 80 4.7 (1) nói rằng nó được thực hiện xác định, không được xác định. Không chắc chắn nếu một thực hiện là miễn phí để xác định nó là hành vi không xác định, tuy nhiên :-) – 6502

6

Đây là implementation defined hành vi, ví dụ gccIntegers Implementation document nói:

Đối với chuyển đổi sang một loại rộng N, giá trị là rút gọn theo modulo 2^N là trong phạm vi của các loại; không có tín hiệu được nâng lên.

Điều này có thể khác với trình biên dịch sang trình biên dịch, tôi không thể đào các tài liệu tương tự cho clang cũng không visual studio.

Từ dự thảo chuẩn C++, phần 4.7 Integral conversions đoạn 3:

Nếu loại đích được ký kết, giá trị là không thay đổi nếu nó có thể được biểu diễn trong các loại đích (và bit lĩnh vực rộng); nếu không, giá trị được thực hiện theo định nghĩa.

Nếu đây là unsigned sau đó bạn sẽ hoàn toàn được xác định rõ hành vi, theo đoạn 2:

Nếu loại đích là unsigned, giá trị kết quả là số nguyên unsigned nhất đồng dư với số nguyên nguồn (modulo 2n trong đó n là số bit được sử dụng để biểu diễn loại unsigned). [Lưu ý: Trong biểu diễn bổ sung của hai, chuyển đổi này là khái niệm và không có thay đổi trong mẫu bit (nếu không có cắt ngắn).—end note]

Ngôn ngữ tương tự trong phần tiêu chuẩn dự thảodự thảo 6.3.1.3 Signed and unsigned integers.

9

Chuyển đổi giá trị thành một loại đã ký, khi giá trị nguồn không phù hợp với loại mục tiêu, hãy mang lại kết quả được xác định thực hiện. Điều đó có nghĩa là bất kỳ tài liệu nào của trình biên dịch phù hợp phải ghi lại kết quả đó là gì.

(Điều này là không giống như các hành vi trên tràn của một toán tử số học Ví dụ:.

int overflow = INT_MAX + 1; 

thực sự có hành vi undefined Nhưng trong cả hai trường hợp, bạn nên cẩn thận để viết mã của bạn để nó doesn. Để kích hoạt loại vấn đề này.)

Đối với nhiều triển khai, cho cả chuyển đổi và số học, tràn mà đích là loại N-bit chỉ cần lấy N bit thứ tự thấp của kết quả chính xác.

Trong trường hợp của bạn, rõ ràng int là 32 bit và short là 16 bit (các kích thước có thể khác nhau trên các triển khai khác nhau). 21474836470x7fffffff, thứ tự 16 bit thấp là 0xffff, đó là (một lần nữa, khi bạn triển khai) biểu thị của -1 trong loại short.

Để chuyển đổi thành loại chưa ký, kết quả được xác định nghiêm ngặt theo tiêu chuẩn; nó có các bit N thứ tự thấp của kết quả. Và đối với việc chuyển đổi dấu chấm động tràn (giả sử, chuyển đổi giá trị double rất lớn thành float), hành vi này là không xác định.

Cho đến nay, điều này cũng giống nhau đối với C và C++. Nhưng chỉ để thêm vào sự nhầm lẫn, bắt đầu với tiêu chuẩn năm 1999, một chuyển đổi có dấu tràn được phép nâng cao một tín hiệu được xác định. C++ không có cái này. Tôi không biết bất kỳ trình biên dịch nào thực sự làm điều này.

Tôi mong đợi để xem một số giá trị và không-1.

-1 "một số giá trị". Có một số giá trị cụ thể mà bạn mong đợi không?

Ngẫu nhiên:

short b = (short)a; 

Dàn diễn viên là không cần thiết. Các lệnh gán, khởi tạo, truyền tham số và các câu lệnh return có thể gán các giá trị giữa bất kỳ loại số nào mà không có phép đúc. Giá trị được chuyển đổi ngầm:

short b = a; 
3

Bạn có thể làm điều này:

uint32_t sum=0xFFFF1234; 
uint16_t *p= (uint16_t *) ∑ 
uint16_t checksum=p[0]; 

check-sum là 0x1234.

Đây là một cách khác:

union ToShort 
{ 
     uint32_t sum; 
     uint16_t checksum[2]; 
} toShort; 
toShort.sum=0xFFFF1234; 
cout << hex << toShort.checksum[0]; 

ra là 1234.