Неверное преобразование из 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]

Это скомпилировано на gcc версии 4.6.3 на Ubuntu 12.10 на 32-разрядной машине Intel.

Учитывая, что char тип unsigned char на x86. -

Если присвоения в строках 7 и 8 для типов без указателей являются Ок, то почему ошибки выбрасываются для типов указателей в строках 10 и 11?

Кроме того, если C = U удастся, не требуя приведения в действие?

Ответ 1

Прежде всего, важно подчеркнуть тот факт, что char, signed char и unsigned char - все разные типы. Раздел 4.10 стандарта С++ 11 определяет три возможных стандартных преобразования указателей между указателями разных типов:

1. Константа нулевого указателя представляет собой целочисленное константное выражение (5.19) prvalue целочисленного типа, которое вычисляет нуль или значение prtyue типа std:: nullptr_t. Константа нулевого указателя может быть преобразована в тип указателя; результатом является нулевое значение указателя этого типа и отличается от любого другого значения указателя объекта или типа указателя функции. Такое преобразование называется преобразованием нулевого указателя. Два значения нулевого указателя того же типа сравниваются равными. Преобразование константы с нулевым указателем в указатель на тип с квалификацией cv - это одно преобразование, а не последовательность преобразования указателя с последующим квалификационным преобразованием (4.4). Константу нулевого указателя интегрального типа можно преобразовать в prvalue типа std:: nullptr_t. [Примечание: полученное значение prvalue не является нулевым значением указателя. -end note]

Это не актуально, так как здесь нет указателей на нуль типа nulltptr_t.

2. Prvalue типа "указатель на cv T", где T - тип объекта, может быть преобразован в prvalue типа "указатель на cv void". Результат преобразования "указателя на cv T" в "указатель на cv void" указывает на начало места хранения, где находится объект типа T, как если бы объект был наиболее производным объектом (1.8) типа T (то есть не подобъектом базового класса). Значение нулевого указателя преобразуется в значение нулевого указателя тип назначения.

Это не может применяться, поскольку тип назначения не void. Наконец,

3. Prvalue типа "указатель на cv D", где D - тип класса, может быть преобразован в prvalue типа "указатель на cv B", где B является базовым классом (п .10) D. Если B является недоступным (п. 11) или двусмысленным (10.2) базовым классом D, программа, которая требует этого преобразования, плохо сформирована. Результатом преобразования является указатель на подобъект базового класса объекта производного класса. Значение нулевого указателя преобразуется в значение нулевого указателя для типа адресата.

signed char не является базовым классом char, поэтому даже это не относится.

Следовательно, неявное стандартное преобразование указателя от signed char до char не может быть выполнено.

С другой стороны, конверсии между значениями интегральных типов разрешены в соответствии с тем, что указано в пункте 4.7.

Ответ 2

У С++ нет автоматического преобразования указателя, неважно, каковы типы указателей на каждой стороне задания, если они разные, вам нужно сделать трансляцию.

Ответ 3

char - это отличный тип от unsigned char и signed char. Гарантируется, что одно из них имеет эквивалентное представление значений, но оно по-прежнему является отдельным типом. Поэтому вы не можете конвертировать из unsigned char* или signed char* в char* (то есть, если вы не используете reinterpret_cast). С++ просто не допускает преобразования указателей между различными типами, например, потому что тогда один тип может маскироваться как другой.

Однако преобразование из unsigned char или signed char в char отлично, потому что оно просто включает в себя преобразование его значения.

Считайте это так: вы можете преобразовать int в float, но вы не можете преобразовать int* в float*.

Ответ 4

Я мог ошибаться, но, как сказано выше, когда вы назначили "C = S; C = U;", С++ автоматически преобразует его, как если бы вы "char x =" h "; printf (" % я ", x);". Однако указатели указывают на определенное место в памяти, и это местоположение имеет размер. Поэтому при преобразовании вида просто смотрятся на значения под разными углами, указывая на разные значения, может потребоваться изменение размера значения, на которое указывает.