|
|
  |
memcpy(void * __restrict , const void * __restrict, size_t ); |
|
|
|
Mar 1 2013, 23:33
|
Местный
  
Группа: Участник
Сообщений: 328
Регистрация: 1-06-06
Из: USA
Пользователь №: 17 672

|
имеется Код typedef struct { uint8_t type; uint16_t len; uint8_t *info; } pack_s; ... pack_s *p_src, *p_dst; uint8_t info[SIZE]; // оба p уже установлены к этому моменту, причем, p_dst, где-то внутри info, поэтому стоит адрес // учтите, логика, проверена и работает на х86 memcpy(&p_dst->data, p_src->data, p_src->len); Так как пакеты создаются извне и размещается в памяти последовательно, т.е. начало пакета может случиться по любому адресу, необходимо использовать, например, #pragma __pack(1), но тогда идет ошибка компиляции из-за __restrict. Прошу заметить, оптимизация отключена, как и С99, т.е. ANSI-C без прибамбасов. Если убрать прагму, то ARMCC НЕПОНЯТНО ЗАЧЕМ выравнивает поинтер на границу 32-битного слова и, по-сему, портит структуру. Не желаю вместо memcpy использовать свой С-код. Вопросы к публике: есть ли у кого инлайн ассемблер для менее привередлигого memcpy или другие разумные предложения. PS: НЕПОНЯТНО ЗАЧЕМ употребил потому, что НЕ понимаю как выравнивание может играть роль в случае указателя, который может быть установлен на любой адрес. Спасибо.
--------------------
|
|
|
|
|
Mar 2 2013, 05:08
|
Участник

Группа: Участник
Сообщений: 63
Регистрация: 15-11-10
Из: Санкт-Петербург
Пользователь №: 60 892

|
Цитата(pitt @ Mar 2 2013, 03:33)  Так как пакеты создаются извне и размещается в памяти последовательно, т.е. начало пакета может случиться по любому адресу, необходимо использовать, например, #pragma __pack(1) Очень сомнительное утверждение. Продумайте логику работы програмы. А самое главное - собирая в памяти последовательно пакеты вы наверняка порождаете ненужную энтропию и сильно ломаете устойчивость кода к нештатным ситуациям. На самом деле выравнивание позволяет чуть быстрее работать с данными. При этом выравнивание самих структур практически никогда не мешает, а вот выравнивание полей структуры... Но судя по коду это не Ваш случай. Цитата(pitt @ Mar 2 2013, 03:33)  Вопросы к публике: есть ли у кого инлайн ассемблер для менее привередлигого memcpy или другие разумные предложения. Хм... Категорически не советую опускаться до ассемблера. Нагородите. По факту - ну напишите свой не привередливый memcpy. Примеров реализации разной степени оптимизированности навалом. А вообще почитайте внимательно мануал на тему memcpy. Ответ на Ваш вопрос там. И сдается мне, что дело тут не в __restrict, а в const. Кстати, а какой ARM? Старые ядра (класса ARM7TDMI) предуют выравненного обращения к словам и двойным словам иначе ловят data abort.
Сообщение отредактировал Alex A. Mihaylov - Mar 2 2013, 05:08
|
|
|
|
|
Mar 2 2013, 06:05
|
Знающий
   
Группа: Участник
Сообщений: 537
Регистрация: 22-02-06
Пользователь №: 14 594

|
Цитата(pitt @ Mar 2 2013, 03:33)  НЕПОНЯТНО ЗАЧЕМ употребил потому, что НЕ понимаю как выравнивание может играть роль в случае указателя, который может быть установлен на любой адрес. Конечно вы не понимаете, так как похоже не читали описание этой дериктивы. Она влияет на стрктуры, юнионы для того, чтобы данные размещались в них с выравниванием. Простой пример: 8 битный компилятор как правило по умолчанию размещает данные с выравниванием на 1 байт, а 32 битный - на 4 байта, в итоге структуры в одном компиляторы будут одного размера, а в другом - другого, и если передавать данные структурами, например в USB или TCP или в любом вашем протоколе, или сохранять на одном а открывать на другом, то конечно попадания байт-в-байт не будет. Для этого и применяется эта прагма. Если же эти структуры используются внутри одного приложения и ни кем больше, то pack как правило вообще не нужен.
|
|
|
|
|
Mar 2 2013, 11:06
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(pitt @ Mar 2 2013, 00:33)  // учтите, логика, проверена и работает на х86 memcpy(&p_dst->data, p_src->data, p_src->len); Работает? Это же просто каша в коде написана! 1. Где поле data в в структуре типа pack_s? Может, имеется ввиду ->info? 2. Если поле info есть указатель, почему первый параметр по ссылке (с &)? Мои догадки: 1. info[SIZE] есть, видимо, какой-то общий буфер, в котором где-то "вложена" структура pack_s, которая, похоже, представляет собой блок данных, предваренный его типом и длиной. В этом случае структуру следует записать как Код typedef __packed struct { uint8_t type; uint16_t len; uint8_t data[1]; } pack_s; понимая, что data[1] на самом деле есть сам буфер переменной длины, а не указатель на куда-то еще. 2. Возможен и другой вариант: структура pack_s в виде от автора есть просто некий универсальный описатель, который, будучи наложен на последовательность байт, выглядит как я описал выше, а будучи использован где-то внутри кода, - действительно не содержит данные, а указывает на еще один буфер с ними посредством *info. Это подозрение следует из memcpy(&p_dst->data, p_src->data, p_src->len), где, к слову, вместо data должно быть info, а имя для info[SIZE] есть просто катастрофа с бодуна, и должно быть выбрано иным. Ну тогда уж надо бы написать: Код #pragma anon_unions typedef __packed struct { uint8_t type; uint16_t len; __packed uinon { uint8_t data[1]; uint8_t *info; } } pack_s; ... memcpy(p_dst->data, p_src->info, p_src->len); // или memcpy(p_dst->info, p_src->data, p_src->len); Я написал два варианта memcpy, т.к. это автор знает, что на что у него "положено", пусть уточнит.
Сообщение отредактировал KnightIgor - Mar 2 2013, 11:09
|
|
|
|
|
Mar 2 2013, 13:39
|
Местный
  
Группа: Участник
Сообщений: 328
Регистрация: 1-06-06
Из: USA
Пользователь №: 17 672

|
Cortex-M3 Да, действительно ->info. Код void c_copy (void *d, const void *s, uint16_t len) { uint16_t i;
for (i = 0; i < len; i++} *d++ = *s++; } Не создает никаких проблем.
--------------------
|
|
|
|
|
Mar 2 2013, 15:13
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(pitt @ Mar 2 2013, 14:39)  Код void c_copy (void *d, const void *s, uint16_t len) { uint16_t i; for (i = 0; i < len; i++} *d++ = *s++; } Не создает никаких проблем. Проблема №1 - закрывающая фигурная скобка вместо круглой в for Проблема №2 "error: #852: expression must be a pointer to a complete object type", причем два раза: вот у Вас указатель void, так откуда ++ будет знать, на сколько двигать указатель? Приведенный выше код - это расчленёнка, как криминалисты говорят.
|
|
|
|
|
Mar 2 2013, 20:45
|
Местный
  
Группа: Участник
Сообщений: 328
Регистрация: 1-06-06
Из: USA
Пользователь №: 17 672

|
Код /* string.h: ANSI 'C' (X3J11 Oct 88) library header, section 4.11 */ /* Copyright (C) Codemist Ltd., 1988-1993. */ /* Copyright 1991-1993 ARM Limited. All rights reserved. */ /* version 0.04 */
/* * RCS $Revision: 137748 $ * Checkin $Date: 2008-09-11 17:34:24 +0100 (Thu, 11 Sep 2008) $ */ ........ extern _ARMABI void *memcpy(void * __restrict /*s1*/, const void * __restrict /*s2*/, size_t /*n*/) __attribute__((__nonnull__(1,2))); /* * copies n characters from the object pointed to by s2 into the object * pointed to by s1. If copying takes place between objects that overlap, * the behaviour is undefined. * Returns: the value of s1. */ ........ Цитата(KnightIgor @ Mar 2 2013, 12:22)  Так что не нужно множить сущности.
--------------------
|
|
|
|
|
Mar 3 2013, 07:45
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 24-11-07
Пользователь №: 32 633

|
Цитата(pitt @ Mar 3 2013, 00:45)  Код * If copying takes place between objects that overlap, * the behaviour is undefined. * Returns: the value of s1. */ ........ Конкретно для этого случая есть в наличие тоже стандартная memove();
|
|
|
|
|
Mar 3 2013, 13:07
|
Местный
  
Группа: Участник
Сообщений: 328
Регистрация: 1-06-06
Из: USA
Пользователь №: 17 672

|
Цитата(PheeL @ Mar 3 2013, 02:45)  Конкретно для этого случая есть в наличие тоже стандартная memove(); Нету перекрытия, конкретно не тот случай. Повторяю: проблема в том, что __restrict в определении memcpy не компилируется, когда включен __packed(1) , а без него, компилятор выравнивает структуру, изменяя ее размер, что недопустимо. Вопрос в том, что может ли кто предложить решение эффективней C-copy(). Спасибо.
--------------------
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|