переинтерпретировать приведение к и без знака char * и char * - PullRequest
3 голосов
/ 05 августа 2009

Мне интересно, нужно ли переинтерпретировать в функции ниже. ITER_T может быть итератором char *, unsigned char *, std :: vector или чем-то подобным. Кажется, пока это не больно, но влияет ли приведение когда-либо на то, как копируются байты?

template<class ITER_T>
char *copy_binary(
  unsigned char length,
  const ITER_T& begin)
{
  // alloc_storage() returns a char*
  unsigned char* stg = reinterpret_cast<unsigned char*>(alloc_storage(length));
  std::copy(begin, begin + length, stg);
  return reinterpret_cast<char*>(stg);
}

Ответы [ 4 ]

6 голосов
/ 05 августа 2009

reinterpret_casts используются для низкоуровневой реализации определенных приведений. Согласно стандарту reinterpret_casts может использоваться для следующих преобразований (C ++ 03 5.2.10):

  • Указатель на целочисленный тип
  • Интегральный тип для указателя
  • Указатель на функцию можно преобразовать в указатель на функцию другого типа
  • Указатель на объект может быть преобразован в указатель на объект другого типа
  • Указатель на функции-члены или указатель на члены-данные могут быть преобразованы в функции или объекты другого типа. Результат такого преобразования указателя не определен, за исключением того, что указатель преобразован обратно в исходный тип.
  • Выражение типа A может быть преобразовано в ссылку на тип B, если указатель на тип A может быть явно преобразован в тип B с помощью reinterpret_cast.

Тем не менее, использование reinterpret_cast не является хорошим решением в вашем случае, поскольку приведение к разным типам не определено стандартом, хотя приведение от char * к unsigned char * и обратно должно работать на большинстве машин. 1023 *

В вашем случае я бы подумал об использовании static_cast или не приведении к типу вообще, определив stg как тип char *:

template<class ITER_T>
char *copy_binary(
  unsigned char length,
  const ITER_T& begin)
{
  // alloc_storage() returns a char*
  char* stg = alloc_storage(length);
  std::copy(begin, begin + length, stg);
  return stg;
}
1 голос
/ 11 октября 2009

Короткий ответ - да, это может повлиять.

char и unsigned char являются конвертируемыми типами (3.9.1 в C ++ Standard 0x n2800), поэтому вы можете назначать один другому. Тебе вообще не нужен актерский состав.

[3.9.1] ... Символ, подписанный символ и неподписанный символ занимает одинаковое количество памяти и имеют одинаковое выравнивание требования; то есть у них есть то же представление объекта .


[4.7] ...

2 Если тип назначения без знака, полученное значение наименьшее целое число без знака соответствует целое число источника (по модулю 2n, где n это количество битов, используемых для представляют тип без знака).

[Примечание: В дополнительном представлении двух это преобразование является концептуальным и нет изменений в битовой комбинации (если нет усечения). —Конечная записка ]

3 Если тип назначения подписан, значение не изменяется , если оно может быть представлены в типе назначения (и ширина битового поля); в противном случае значение определяется реализацией.

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

template<class ITER_T>
char *copy_binary( unsigned char length, const ITER_T& begin)
{
  char* stg = alloc_storage(length);
  std::copy(begin, begin + length, stg);
  return stg;
}

Использование reinterpret_cast зависит от компилятора:

[5.2.10.3] Отображение, выполненное reinterpret_cast is от реализации . [ Обратите внимание может или не может производить представление отличается от первоначальная стоимость —Конечная записка]

Примечание: Этот - интересный связанный пост.

1 голос
/ 05 августа 2009

Написанный код работает как задумано в соответствии со стандартом 4.7 (2), хотя это гарантировано только для машин с представлением дополнения до двух.

Если alloc_storage возвращает char *, а 'char' подписан, то, если я правильно понимаю 4.7 (3), результат будет определен реализацией, если тип значения итератора будет беззнаковым и вы отбросите приведение и передадите char * скопировать.

0 голосов
/ 05 августа 2009

Так что, если я правильно понял, приведение к неподписанному символу - это проверка неподписанной побайтовой копии. Но затем вы отбрасываете его обратно для возвращения. Функция выглядит немного хитроумно, каков именно контекст / причина для ее настройки таким образом? Быстрое решение может состоять в том, чтобы заменить все это на memcpy () (но, как прокомментировано, не используйте это на объектах итератора) - в противном случае просто удалите лишние приведения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...