Мнения о трамбовке типа в C++?

22
задан Tom 10 February 2010 в 06:20
поделиться

3 ответа

Насколько стандарт C++ затронут, , ответ litb является абсолютно корректным и самым портативным. Кастинг const char *data к const uint3_t *, нарушает ли это быть через бросок C-стиля, static_cast, или reinterpret_cast, строгие правила искажения (см. Понимать Строгое Искажение ). Если Вы компилируете с полной оптимизацией, существует хороший шанс, код не будет к правильной вещи.

Кастинг через объединение (такое как litb's my_reint) является, вероятно, лучшим решением, хотя это действительно технически нарушает правило, что, если Вы пишете в объединение через одного участника и читаете его через другого, это приводит к неопределенному поведению. Однако практически все компиляторы поддерживают это, и это приводит к ожидаемый результат. Если Вы абсолютно требуете соответствовать стандартным 100%, пойдите со смещающим бит методом. Иначе я рекомендовал бы идти с кастингом через объединение, которое, вероятно, даст Вам лучшую производительность.

13
ответ дан Community 29 November 2019 в 05:53
поделиться

Игнорирование эффективности, для простоты кода я сделал бы:

#include <numeric>
#include <vector>
#include <cstring>

uint32_t compute_checksum(const char *data, size_t size) {
    std::vector<uint32_t> intdata(size/sizeof(uint32_t));
    std::memcpy(&intdata[0], data, size);
    return std::accumulate(intdata.begin(), intdata.end(), 0);
}

мне также нравится последний ответ litb, тот, который смещает каждый символ в свою очередь, за исключением того, что, так как символ мог бы быть подписан, я думаю, что этому нужна дополнительная маска:

checksum += ((data[i] && 0xFF) << shift[i % 4]);

, Когда трамбовка типа является потенциальной проблемой, я предпочитаю не вводить игру слов, а не пытаться сделать так безопасно. Если Вы не создаете искаженных указателей отличных типов во-первых, то Вы не должны волновать то, что компилятор мог бы сделать с псевдонимами, и ни один не делает программиста обслуживания, который видит Ваши несколько static_casts через объединение.

, Если Вы не хотите выделять так много дополнительной памяти, тогда:

uint32_t compute_checksum(const char *data, size_t size) {
    uint32_t total = 0;
    for (size_t i = 0; i < size; i += sizeof(uint32_t)) {
        uint32_t thisone;
        std::memcpy(&thisone, &data[i], sizeof(uint32_t));
        total += thisone;
    }
    return total;
}

Достаточно оптимизации избавится от memcpy и дополнительной uint32_t переменной полностью на gcc, и просто считает невыровненное целочисленное значение, в том, что самый эффективный способ сделать, который находится на Вашей платформе, прямо из исходного массива. Я надеялся бы, что то же верно для других "серьезных" компиляторов. Но этот код теперь больше, чем litb's, таким образом, нет очень, чтобы быть сказанным для него кроме моего, легче превратиться в шаблон функции, который будет работать точно также с uint64_t и работами шахты как собственный порядок байтов вместо того, чтобы выбрать прямой порядок байтов.

Это, конечно, не абсолютно портативно. Это предполагает, что представление устройства хранения данных sizeof (uint32_t) символы соответствует представлению устройства хранения данных uin32_t в способе, которым мы хотим. Это подразумевается вопросом, так как он указывает, что можно "рассматриваться как" другой. Порядок байтов, является ли символ 8 битами, и использует ли uint32_t все биты в своем представлении устройства хранения данных, может, очевидно, нарушить, но вопрос подразумевает, что они не будут.

6
ответ дан Steve Jessop 29 November 2019 в 05:53
поделиться

Это похоже на пример журнала того, когда использовать reinterpret_cast, что-либо еще даст Вам тот же эффект без явности, которую Вы получаете от использования конструкции языка для ее служебного пользования.

-4
ответ дан Motti 29 November 2019 в 05:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: