2013-02-23 73 views
10

Đây là một mã -chuyển đổi không hợp lệ từ unsigned char * để char *

1 int main(int argc, char *argv[]) 
    2 { 
    3  signed char S, *psc; 
    4  unsigned char U, *pusc; 
    5  char C, *pc; 
    6 
    7  C = S; 
    8  C = U; 
    9 
10  pc = psc; 
11  pc = pusc; 
12 
13  return 0; 
14 } 

$ gcc test.cpp -o a 
test.cpp: In function ‘int main(int, char**)’: 
test.cpp:10:7: error: invalid conversion from ‘signed char*’ to ‘char*’ [-fpermissive] 
test.cpp:11:7: error: invalid conversion from ‘unsigned char*’ to ‘char*’ [-fpermissive] 

này được biên soạn trên phiên bản gcc 4.6.3 trên Ubuntu 12.10 trên một máy Intel 32-bit.

Xét rằng char loại là unsigned char trên x86. -

Nếu bài tập trên dòng 7 và 8 cho loại không phải con trỏ là Ok, tại sao lỗi được ném cho loại con trỏ trên dòng 10 và 11?

Ngoài ra, nên C = U thành công mà không yêu cầu dàn diễn viên?

+0

Bạn có quen thuộc với thuật ngữ ["bí danh nghiêm ngặt"] không (http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html)? – WhozCraig

+0

Đọc nội dung đó ... – nightlytrails

+1

'-fpermissive' có thể giúp bạn và bỏ qua sự khó chịu này. Đôi khi bạn có thể muốn tạm thời xóa thẻ và xem liệu trình biên dịch của bạn có phát hiện các lỗi khác so với lỗi này trong dự án của bạn mà bạn * nên lo lắng không. – rsethc

Trả lời

1

C++ không có chuyển đổi con trỏ tự động, nó không quan trọng các loại con trỏ trên mỗi bên của nhiệm vụ, nếu chúng khác nhau, bạn cần một diễn viên.

1

char là một loại riêng biệt từ unsigned charsigned char. Nó chỉ được đảm bảo có đại diện giá trị tương đương với một trong số chúng, nhưng nó vẫn là một kiểu riêng biệt. Do đó, bạn không thể quy đổi từ unsigned char* hoặc signed char* thành char* (nghĩa là, trừ khi bạn sử dụng reinterpret_cast). C++ không cho phép chuyển đổi con trỏ giữa các loại khác biệt như thế này, bởi vì sau đó một loại có thể giả mạo như một loại khác.

Tuy nhiên, chuyển đổi từ unsigned char hoặc signed char thành char hoàn toàn ổn vì nó chỉ liên quan đến chuyển đổi giá trị của nó.

Hãy xem xét theo cách này: bạn có thể chuyển đổi int thành float, nhưng bạn không thể chuyển đổi một int* thành float*.

6

Trước hết, điều quan trọng là phải nhấn mạnh một thực tế rằng char, signed char, và unsigned char đều loại khác nhau. Mục 4.10 của tiêu chuẩn C++ 11 xác định ba chuyển đổi con trỏ chuẩn có thể có giữa các con trỏ thuộc các loại khác nhau:

1. Một hằng số con trỏ null là một biểu thức hằng số không thể tách rời (5.19) prvalue của kiểu số nguyên mà đánh giá bằng không hoặc một giá trị của kiểu std :: nullptr_t. Một hằng số con trỏ null có thể được chuyển đổi thành kiểu con trỏ; kết quả là giá trị con trỏ null của kiểu đó và có thể phân biệt với mọi giá trị khác của con trỏ đối tượng hoặc kiểu con trỏ hàm. Chuyển đổi như vậy được gọi là chuyển đổi con trỏ null. Hai giá trị con trỏ null của cùng loại sẽ so sánh bằng nhau. Việc chuyển đổi hằng số con trỏ null thành con trỏ thành loại cv đủ điều kiện là một chuyển đổi duy nhất, và không phải là chuỗi chuyển đổi con trỏ theo sau bởi một chuyển đổi tiêu chuẩn (4.4). Một hằng số con trỏ null của kiểu tích phân có thể được chuyển đổi thành một giá trị của kiểu std :: nullptr_t. [Ghi chú: Giá trị kết quả không phải là giá trị con trỏ null. —end note]

Điều này không liên quan, vì chúng tôi không có con trỏ null loại nulltptr_t tại đây.

2. Giá trị của loại "con trỏ tới cv T", trong đó T là một loại đối tượng, có thể được chuyển đổi thành giá trị của loại "con trỏ thành cv void".Kết quả của việc chuyển đổi “con trỏ thành cv T” thành điểm “con trỏ tới cv void” để bắt đầu vị trí lưu trữ nơi đối tượng của kiểu T cư trú, như thể đối tượng là đối tượng có nguồn gốc cao nhất (1.8) của kiểu T (nghĩa là, không phải là một lớp con cơ sở). Giá trị con trỏ null được chuyển thành giá trị con trỏ null của loại đích .

Điều này không thể áp dụng, vì loại đích không phải là void. Cuối cùng,

3. Giá trị của loại "con trỏ đến cv D", trong đó D là một loại lớp, có thể được chuyển đổi thành giá trị của loại "con trỏ đến cv B", trong đó B là một lớp cơ sở (Điều 10) của D. Nếu B là một không thể tiếp cận (Điều 11) hoặc lớp cơ sở không rõ ràng (10.2) của D, một chương trình yêu cầu chuyển đổi này là không đúng định dạng. Kết quả của việc chuyển đổi là một con trỏ tới lớp con cơ sở của đối tượng lớp dẫn xuất. Giá trị con trỏ null được chuyển đổi thành giá trị con trỏ null của loại đích là .

signed char không phải là lớp cơ sở là char, vì vậy, ngay cả điều này cũng không áp dụng.

Do đó, chuyển đổi con trỏ chuẩn, tiềm ẩn từ signed char thành char không thể thực hiện được.

Mặt khác, chuyển đổi giữa các giá trị của các loại tích phân được cho phép theo những gì được quy định trong Đoạn 4.7.

+1

Tôi nghĩ, điều quan trọng cần nhấn mạnh là 'char',' unsigned char' và 'signed char' là 3 kiểu khác nhau. Tôi nghi ngờ câu hỏi xuất phát từ quan niệm sai lầm, rằng 'char' là' char char' hoặc 'unsigned char'. –

+0

@MaciejHehl: Đúng vậy. Tôi đã chỉnh sửa câu trả lời, cảm ơn bạn. –

0

Tôi có thể sai, nhưng như đã nói ở trên, khi bạn gán "C = S; C = U;", C++ tự động chuyển đổi nó, giống như bạn làm "char x =" h "; printf ("% i ", x);". Tuy nhiên, con trỏ trỏ đến một vị trí cụ thể trong bộ nhớ và vị trí đó có kích thước. Vì vậy, trong khi chuyển đổi loại chỉ nhìn vào các giá trị từ một góc độ khác nhau, chỉ vào các giá trị khác nhau có thể liên quan đến việc thay đổi kích thước của giá trị đang được chỉ ra.

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