这是一个代码 -
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]
这是在英特尔 32 位机器上的 Ubuntu 12.10 上的 gcc 版本 4.6.3 上编译的。
考虑到char
类型在x86上unsigned char
。
如果第 7 行和第 8 行的非指针类型的赋值为 Ok,为什么第 10 行和第 11 行的指针类型会抛出错误?
另外,C = U
应该在不需要石膏的情况下成功吗?
首先,需要强调的是,char
、signed char
和unsigned char
都是不同的类型。C++11 标准的第 4.10 节定义了不同类型的指针之间的三种可能的标准指针转换:
1 .空指针常量是整数类型的整数类型的整数常量表达式 (5.19( prvalue,其计算结果为零或 std::nullptr_t 类型的 prvalue。空指针常量可以转换为指针类型;结果是该类型的 null 指针值,并且可以与对象指针或函数指针类型的所有其他值区分开来。此类转换称为空指针转换。相同类型的两个空指针值应相等。将 null 指针常量转换为指向 cv 限定类型的指针是单个转换,而不是指针转换后进行限定转换的顺序 (4.4(。 整型的空指针常量可以转换为 std::nullptr_t 类型的 prvalue。 [ 注意:生成的 prvalue 不是空指针值。
这无关紧要,因为我们这里没有 nulltptr_t
类型的空指针。
阿拉伯数字。类型为"指向 cv T 的指针"(其中 T 是对象类型(的 prvalue 可以转换为类型为"指向 cv void 的指针"的 prvalue。将"指向 cv T 的指针"转换为"指向 cv void 的指针"的结果指向类型为 T 的对象所在的存储位置的开头,就好像该对象是 T 类型的派生最多的对象 (1.8((即,不是基类子对象(。空指针值将转换为 目标类型。
这不适用,因为目标类型不是 void
。最后
3 .类型为"指向 cv D 的指针"的 prvalue,其中 D 是类类型,可以转换为类型为"指向 cv B 的指针"的 prvalue,其中 B 是 D 的基类(条款 10(。如果 B 是 D 的不可访问(条款 11(或不明确的 (10.2( 基类,则需要此转换的程序格式不正确。转换的结果是指向派生类对象的基类子对象的指针。空指针值将转换为 目标类型的空指针值。
signed char
不是char
的基类,所以即使这样也不适用。
因此,无法执行从 signed char
到 char
的隐式标准指针转换。
另一方面,根据第 4.7 段的规定,允许整数类型值之间的转换。
自动指针转换,作业每一端的指针类型是什么并不重要,如果它们不同,则需要强制转换。
char
是与unsigned char
和signed char
不同的类型。它只能保证与其中一个具有等效的值表示形式,但它仍然是一个不同的类型。因此,您无法从 unsigned char*
或 signed char*
转换为 char*
(即,除非您使用 reinterpret_cast
(。C++只是不允许像这样在不同类型之间进行指针转换,因为这样一种类型可能会伪装成另一种类型。
但是,从unsigned char
或signed char
到char
的转换是完全可以的,因为它只涉及其值的转换。
可以这样考虑:您可以将int
转换为float
,但不能将int*
转换为float*
。
我可能是错的,但如上所述,当您分配"C = S;C = U;",C++自动转换它,有点像你做"char x = "h";printf("%i", x(;".但是,指针指向内存中的特定位置,并且该位置具有大小。因此,虽然转换只是从不同的角度查看值,但指向不同的值可能涉及更改所指向的值的大小。