Мне любопытно о соглашениях для указателей/массивов типа-punning в C++. Вот пример использования, который у меня есть на данный момент:Мнения о типах каламбуров в C++?
Вычислить простую 32-битную контрольную сумму над двоичным блоком данных, рассматривая его как массив из 32-битных целых чисел (мы знаем, что его общая длина кратна 4), а затем суммируя все значения и игнорируя переполнение.
Я бы ожидать такой функции, чтобы выглядеть следующим образом:
uint32_t compute_checksum(const char *data, size_t size)
{
const uint32_t *udata = /* ??? */;
uint32_t checksum = 0;
for (size_t i = 0; i != size/4; ++i)
checksum += udata[i];
return udata;
}
Теперь вопрос у меня есть, что вы считаете «лучший» способ преобразования data
в udata
?
C-style cast?
udata = (const uint32_t *)data
C++ cast, который предполагает, что все указатели являются конвертируемыми?
udata = reinterpret_cast<const uint32_t *>(data)
C++ отливать, что между произвольными типами указателей с использованием промежуточного void*
?
udata = static_cast<const uint32_t *>(static_cast<const void *>(data))
Кастинг через союз?
union {
const uint32_t *udata;
const char *cdata;
};
cdata = data;
// now use udata
Я полностью понимаю, что это не будет 100% портативный раствор, но я только ожидая, чтобы использовать его на небольшой набор платформ, где я знаю, что это работает (а именно выровненным доступа к памяти и предположения компилятора по указателю сглаживание). Чтобы вы посоветовали?
Решения litb правильны по стандарту - но, как я уже сказал, я уже рассматриваю конкретные платформы. – Tom 2008-12-07 07:01:01
Я не уверен, почему они downvote это :), но я также не уверен, что мое использование союза - неопределенное поведение. Я знаю, что запись в член и чтение из другого члена - неопределенное поведение. Но в моем case, я указываю на его член, который, как предполагается, имеет действительное значение и читает его тогда. – 2008-12-07 12:44:56
Я не думаю, что этот конкретный пример нарушает строгий псевдоним. char * является особым случаем при строгих правилах псевдонимов - char * никогда не может считаться не псевдонимом указателя на какой-либо другой тип. Но в моем ответе я все еще играю в безопасности: просто не стоит делать char * иначе, чем в других подобных случаях. – 2008-12-07 14:07:43