2010-07-19 37 views
5

Trong C++, chúng tôi có thể có signed charunsigned char có cùng kích thước nhưng giữ các phạm vi giá trị khác nhau.Có thể "ký char" và "unsigned char" luôn được truyền cho nhau mà không bị mất dữ liệu?

Trong đoạn mã sau:

signed char signedChar = -10; 
unsigned char unsignedChar = static_cast<unsigned char>(signedChar); 
signedChar = static_cast<signed char>(unsignedChar); 

sẽ signed char giữ lại giá trị của nó bất kể những gì giá trị ban đầu của nó là?

+3

Gần-bản sao của http://stackoverflow.com/questions/50605/signed-to-unsigned-conversion-in-c-is-it-always-safe – dan04

+0

Một câu hỏi khác có thể là một gần bờ trùng lặp, nhưng câu trả lời được chấp nhận của nó là sai. –

Trả lời

-1

Dự đoán đầu tiên của tôi là "có thể". Bạn đã thử nghiệm tính năng này với nhiều đầu vào khác nhau chưa?

+0

Chỉ cần thử nghiệm sẽ không giúp ích - điều đó chỉ có thể cho bạn biết liệu máy tính/trình biên dịch của bạn có hỗ trợ nó hay không. Bạn không thể dựa vào nó trừ khi đó là hành vi được chỉ định. Nếu không, bạn sẽ có những cơn đau đầu vô tận sau này. –

+0

Vì vậy, tôi đoán câu trả lời đúng cho câu hỏi này là, "nó phụ thuộc." ? – AlvinfromDiaspar

0

AFAIK, diễn viên này sẽ không bao giờ thay đổi byte, chỉ cần thay đổi biểu diễn của nó.

10

Không, không có bảo đảm như vậy. Việc chuyển đổi từ signed char thành unsigned char được xác định rõ ràng, vì tất cả chuyển đổi tích phân được ký kết thành dấu trừ trong C++ (và C) là. Tuy nhiên, kết quả của việc chuyển đổi đó có thể dễ dàng hóa ra ngoài giới hạn của loại ký gốc (sẽ xảy ra trong ví dụ của bạn với -10).

Kết quả của việc chuyển đổi ngược lại - unsigned char đến signed char - trong trường hợp đó được thực hiện xác định, vì tất cả chuyển đổi tích phân không ký tên trong C++ (và C) là. Điều này có nghĩa là kết quả không thể dự đoán được từ các quy tắc ngôn ngữ.

Thông thường, bạn nên mong đợi triển khai "xác định" nó sao cho giá trị signed char gốc được khôi phục. Nhưng ngôn ngữ không đảm bảo về điều đó.

+0

Khi số nguyên âm được đúc thành định dạng đã ký, nó chỉ biến thành mã bổ sung của nó (một số số lớn), phải không? Điều này có thể được gọi là mất dữ liệu, nhưng bạn có thể bỏ nó trở lại âm. – alxx

+2

@alxx: Er ... Ý của bạn là "bỏ vào * định dạng không dấu *"? Truyền từ chữ ký sang unsigned được yêu cầu để tạo ra giá trị "modulo". Đó là cách đặc tả ngôn ngữ yêu cầu nó. Cho dù điều đó xảy ra "bởi chính nó" (như trong các máy bổ sung của 2) hay bởi vì trình biên dịch thực hiện các bước để đảm bảo nó là một câu chuyện khác. Đang quay trở lại chữ ký ... Có bạn "có thể" làm điều đó, nhưng một lần nữa, ngôn ngữ không đảm bảo về kết quả. – AnT

+0

đúc ký char -1 để unsigned char yields 255 trên trình biên dịch của tôi để bạn có thể nói rằng có dữ liệu không tương thích .. Tôi do dự để gọi nó mất dữ liệu nhìn thấy như bạn không mất bất cứ điều gì thực sự chỉ có nghĩa là –

1

Tôi đoán ý nghĩa của câu hỏi là chìa khóa là gì. Khi bạn nói mất mát, bạn có nghĩa là bạn đang mất byte hoặc một cái gì đó như thế. Bạn không mất bất cứ thứ gì như vậy vì kích thước của cả hai đều giống nhau, chúng chỉ có phạm vi khác nhau.

char đã ký và char chưa ký sẽ không được đảm bảo bằng nhau. Khi hầu hết mọi người nghĩ rằng unsigned char, họ đang nghĩ từ 0 đến 255.

Trên hầu hết các triển khai (tôi phải báo trước vì có sự khác biệt), ký char và unsigned char là 1 byte hoặc 8 bit. ký char thường từ -128 đến +127 trong khi unsigned char là từ 0 đến +255.

Theo như chuyển đổi, nó còn lại để triển khai khác nhau để đưa ra câu trả lời. Nói chung, tôi sẽ không khuyên bạn nên chuyển đổi giữa hai người. Đối với tôi, nó có ý nghĩa là nó sẽ cung cấp cho bạn tương đương TÍCH CỰC nếu giá trị là tiêu cực và vẫn giữ nguyên nếu là dương. Ví dụ trong Borland C++ Builder 5, được đưa ra signed char test = -1 và bạn đưa nó vào unsigned char, kết quả sẽ là 255. Ngoài ra, kết quả sẽ khác nếu tất cả các giá trị là dương.

Nhưng theo như so sánh, trong khi các giá trị có thể xuất hiện giống nhau, chúng có thể sẽ không được đánh giá như nhau. Đây là một chuyến đi lớn lên khi các lập trình viên đôi khi so sánh các giá trị đã ký và chưa ký và tự hỏi tại sao tất cả dữ liệu trông giống nhau, nhưng điều kiện sẽ không hoạt động đúng. Một trình biên dịch tốt nên cảnh báo bạn về điều này.

Tôi có ý kiến ​​rằng cần có một chuyển đổi tiềm ẩn giữa chữ ký và unsigned để nếu bạn chuyển từ cái này sang cái kia, trình biên dịch sẽ chăm sóc chuyển đổi cho bạn. Việc cài đặt của trình biên dịch là tùy thuộc vào việc bạn có mất ý nghĩa ban đầu hay không. Thật không may là không có đảm bảo rằng nó sẽ luôn luôn làm việc.

Cuối cùng, từ tiêu chuẩn, phải tồn tại một chuyển đổi đơn giản giữa char đã ký hoặc char chưa ký thành char. Nhưng nào nó chọn để có, là thực hiện được xác định

3.9.1 loại cơ bản [basic.fundamental]

1 đối tượng khai báo là ký tự char) phải đủ lớn để lưu trữ bất kỳ viên của việc thực hiện của bộ ký tự cơ bản . Nếu một ký tự từ bộ này được lưu trữ trong một đối tượng ký tự, giá trị tích phân của đối tượng ký tự đó bằng giá trị của dạng ký tự đơn của ký tự đó. Nó là thực hiện được xác định cho dù một đối tượng char có thể giữ giá trị âm. Các ký tự có thể được khai báo rõ ràng chưa ký hoặc được ký. Đồng bằng char, ký char và char chưa ký là ba loại riêng biệt. Một char, một chữ ký có chữ ký, và một ký tự chưa ký chiếm cùng một số lượng lưu trữ và có cùng một yêu cầu liên kết (basic.types); nghĩa là chúng có cùng đối tượng đại diện. Đối với các loại ký tự, tất cả các bit của đối tượng đại diện tham gia vào giá trị đại diện . Đối với ký tự chưa ký loại, tất cả các mẫu bit có thể có của đại diện giá trị đại diện cho số . Những yêu cầu này không giữ các loại khác. Trong bất kỳ triển khai cụ thể nào, đối tượng char đơn giản có thể nhận được các giá trị giống như một thẻ được ký hoặc char chưa ký; cái nào là được xác định thực hiện.

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