Когда преобразование между неподписанным и подписанным символьным указателем становится небезопасным в C?

Если я сделаю это как в clang и в Visual Studio :

  unsigned char *a = 0; char * b = 0; char x = '3'; a = & x; b = (unsigned char*) a; 

Я получаю предупреждение о том, что я пытаюсь преобразовать символ подписанного и неподписанного символов, но код действительно работает. Хотя компилятор говорит это по какой-то причине. Можете ли вы указать на ситуацию, когда это может стать проблемой?

Сделать это очень просто, потому что char представляет:

  • Один символ ( char , это не имеет значения, подписано или нет). Когда вы назначаете символ типа 'A' вы должны написать ASCII-код (65) в этой ячейке памяти.
  • Строка (когда используется как массив или указатель на буфер char ).
  • 8-битное число (с или без знака).

Затем, когда вы конвертируете подписанный байт типа -1 в беззнаковый байт, вы потеряете информацию (хотя бы знак, но, вероятно, номер тоже), поэтому вы получаете предупреждение:

 signed char a = -1; unsigned char b = (unsigned char)a; if ((int)b == -1) ; // No! Now b is 255! 

Значение может быть не 255, а 1, если ваша система не представляет отрицательные числа с дополнением 2, в этом примере это не имеет особого значения (и я никогда не работал с какой-либо системой, как это, но они существуют), поскольку концепция представляет собой подписанный / беззнаковое преобразование может отбрасывать информацию . Не имеет значения, происходит ли это из-за явного приведения или броска через указатели: биты будут представлять что-то другое (и результат будет изменяться в соответствии с реализацией, средой и фактическим значением).

Обратите внимание, что для стандартного char C char signed char и unsigned char формально отличается. Вам все равно (и VS будет по умолчанию char signed или unsigned соответствии с опцией компилятора, но это не переносится), и вам может понадобиться кастинг.

Ваш код правильный (любой тип может быть псевдонимом unsigned char ). Кроме того, в системах дополнений 2 этот псевдоним совпадает с результатом преобразования значений.

Обратная операция; aliasing unsigned char char является проблемой только для эзотерических систем, у которых есть ловушки для простого char .

Я не знаю таких систем, которые когда-либо существовали, хотя стандарт C обеспечивает их существование. К сожалению, из-за этой возможности требуется литье, что более раздражает, чем полезно ИМХО.

Алиасирование unsigned char char совпадает с преобразованием значения в каждой современной системе, о которой я знаю (технически определенная реализация, но все это реализует, что преобразование значений сохраняет одно и то же представление).

NB. определение терминов, взятие, например, unsigned char x = 250; :

  • alias char y = *(char *)&x;
  • преобразование char y = x;

Тип char может быть подписан или без знака в зависимости от платформы. Код, который вы пишете с литьем символа символа без знака или знака, может работать нормально на одной платформе, но не если данные передаются через операционные системы, ETC. См. Этот URL:

http://www.trilithium.com/johan/2005/01/char-types/

Потому что вы можете потерять некоторые ценности – посмотрите на это:

 unsigned char *a = 0; char b = -3; a = &b; printf("%d", *a); 

Результат: 253

Позвольте мне объяснить это. Просто посмотрите на диапазоны:

unsigned char: от 0 до 255
подписанный символ: от -128 до 127

Отредактировано: извините за ошибку, сегодня слишком жарко;)