Intereting Posts
Декодер функций C ++ запускать streamи функции члена classа в c ++ Что такое свисающая ссылка? Использование offsetof () для получения объекта-владельца из переменной-члена Могу ли я вызывать во время выполнения логику выбора того, какой пользовательский литерал для вызова? Я хочу поймать исключение и связать его в своем собственном исключении и бросить вверх как я могу получить доступ к данным последовательного порта в c ++ с помощью wxwidgets В чем смысл неявного конструктора C ++ по умолчанию? Множественное отслеживание в видео QFileSystemModel и QTreeView – странное поведение при сбросе представления Как определить программно, если выражение имеет значение rvalue или lvalue в C ++? c ++ как преобразовать символ в шестнадцатеричный Есть ли причина использовать std :: list? C ++ 11 regex multiline: Почему группа ( + \ n)? Some_text имеет все в матче ? связь между native-app и chrome-extension

Реализация Memcpy, строгий псевдоним

Во время обучения c я реализовал свои собственные функции memcpy. Я использовал более широкий тип ( uint32_t ) в функции. (Для простоты функция ограничена типами, кратными 4, и данные правильно выровнены)

 void memcpy4( void* dst , void* src , int size ) { size /= 4; for ( int i = 0 ; i < size ; i++ ) ((uint32_t*)dst)[i] = ((uint32_t*)src)[i]; } 

Я сделал некоторые чтения по типу punning и строгому псевдониму, и я считаю, что вышеприведенная функция нарушает правило. Правильная реализация будет такой, поскольку вы можете использовать символ:

 void memcpy4( void* dst , void* src , int size ) { for ( int i = 0 ; i < size ; i++ ) ((char *)dst)[i] = ((char *)src)[i]; } 

Я пытался сделать кастинг через союз, но это тоже оказалось недействительным.

Как можно реализовать такую ​​функцию с более широким типом, а не нарушить правило строгого сглаживания?

Способ реализации memcpy с использованием более чем однобайтных копий заключается в использовании нестандартных C.

Стандарт C не поддерживает реализацию memcpy с использованием типов, отличных от символов.

Реализации C качества обеспечивают оптимизированную реализацию memcpy которая выполняет эффективное копирование с использованием более чем однобайтных копий, но для этого используется код, специфичный для реализации. Они могут сделать это, компилируя реализацию memcpy с помощью такого переключателя, как -fnostrict-aliasing чтобы сообщить компилятору, что правила сглаживания будут нарушены в коде, опираясь на известные функции конкретной реализации C, чтобы гарантировать, что код будет работать (если вы пишете компилятор, вы можете его спроектировать так, чтобы ваша реализация memcpy ) или написанием memcpy на ассемблере.

Кроме того, реализации C могут оптимизировать вызовы memcpy где они появляются в исходном коде, заменяя их прямыми инструкциями для выполнения операции или просто изменяя внутреннюю семантику программы. (Например, если вы скопируете a в b , компилятор может вообще не выполнять копию, но может просто загрузить из того, где последует доступ к кодам b ).

Чтобы реализовать свою собственную специализированную операцию копирования при нарушении правил псевдонимов, скомпилируйте ее с помощью -fnostrict-aliasing , если вы используете GCC или Clang. Если вы используете другой компилятор, проверьте его документацию, чтобы отключить правила псевдонимов. (Примечание: GCC от Apple, который я использую, отключает строгий псевдоним по умолчанию и принимает -fstrict-aliasing но не -fnostrict-aliasing . -fnostrict-aliasing что не-Apple GCC принимает -fnostrict-aliasing .)

Если вы используете хорошую реализацию C, вы можете обнаружить, что реализация memcpy4 с memcpy4 не работает так же, как и родная memcpy , в зависимости от обстоятельств.

В дополнение к предположению, что sizeof(uint32_t) == 4 , линия

 size /= 4; 

в вашей первой реализации просто неправильно:

Разделение является целым делением, поэтому оно эффективно вычисляет floor(size/4) . Поэтому, если исходный size не делится на четыре, от одного до трех байтов от источника не будет скопировано в пункт назначения.