let's see 0 1 марта, 2013 Опубликовано 1 марта, 2013 · Жалоба имеется 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: НЕПОНЯТНО ЗАЧЕМ употребил потому, что НЕ понимаю как выравнивание может играть роль в случае указателя, который может быть установлен на любой адрес. Спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
minimumlaw 0 2 марта, 2013 Опубликовано 2 марта, 2013 (изменено) · Жалоба Так как пакеты создаются извне и размещается в памяти последовательно, т.е. начало пакета может случиться по любому адресу, необходимо использовать, например, #pragma __pack(1) Очень сомнительное утверждение. Продумайте логику работы програмы. А самое главное - собирая в памяти последовательно пакеты вы наверняка порождаете ненужную энтропию и сильно ломаете устойчивость кода к нештатным ситуациям. На самом деле выравнивание позволяет чуть быстрее работать с данными. При этом выравнивание самих структур практически никогда не мешает, а вот выравнивание полей структуры... Но судя по коду это не Ваш случай. Вопросы к публике: есть ли у кого инлайн ассемблер для менее привередлигого memcpy или другие разумные предложения. Хм... Категорически не советую опускаться до ассемблера. Нагородите. По факту - ну напишите свой не привередливый memcpy. Примеров реализации разной степени оптимизированности навалом. А вообще почитайте внимательно мануал на тему memcpy. Ответ на Ваш вопрос там. И сдается мне, что дело тут не в __restrict, а в const. Кстати, а какой ARM? Старые ядра (класса ARM7TDMI) предуют выравненного обращения к словам и двойным словам иначе ловят data abort. Изменено 2 марта, 2013 пользователем Alex A. Mihaylov Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kan35 7 2 марта, 2013 Опубликовано 2 марта, 2013 · Жалоба НЕПОНЯТНО ЗАЧЕМ употребил потому, что НЕ понимаю как выравнивание может играть роль в случае указателя, который может быть установлен на любой адрес. Конечно вы не понимаете, так как похоже не читали описание этой дериктивы. Она влияет на стрктуры, юнионы для того, чтобы данные размещались в них с выравниванием. Простой пример: 8 битный компилятор как правило по умолчанию размещает данные с выравниванием на 1 байт, а 32 битный - на 4 байта, в итоге структуры в одном компиляторы будут одного размера, а в другом - другого, и если передавать данные структурами, например в USB или TCP или в любом вашем протоколе, или сохранять на одном а открывать на другом, то конечно попадания байт-в-байт не будет. Для этого и применяется эта прагма. Если же эти структуры используются внутри одного приложения и ни кем больше, то pack как правило вообще не нужен. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KnightIgor 2 2 марта, 2013 Опубликовано 2 марта, 2013 (изменено) · Жалоба // учтите, логика, проверена и работает на х86 memcpy(&p_dst->data, p_src->data, p_src->len); Работает? Это же просто каша в коде написана! 1. Где поле data в в структуре типа pack_s? Может, имеется ввиду ->info? 2. Если поле info есть указатель, почему первый параметр по ссылке (с &)? Мои догадки: 1. info есть, видимо, какой-то общий буфер, в котором где-то "вложена" структура 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 есть просто катастрофа с бодуна, и должно быть выбрано иным. Ну тогда уж надо бы написать: #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, т.к. это автор знает, что на что у него "положено", пусть уточнит. Изменено 2 марта, 2013 пользователем KnightIgor Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kan35 7 2 марта, 2013 Опубликовано 2 марта, 2013 · Жалоба Функции memcpy работает с данными выровненными на байт. Не важно какой процессор, и какое там выравнивание в нем, все эти проблемы решены на уровне С компилятора для данного процессора. И потому не надо писать другие memcpy. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
let's see 0 2 марта, 2013 Опубликовано 2 марта, 2013 · Жалоба 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++; } Не создает никаких проблем. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KnightIgor 2 2 марта, 2013 Опубликовано 2 марта, 2013 · Жалоба 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, так откуда ++ будет знать, на сколько двигать указатель? Приведенный выше код - это расчленёнка, как криминалисты говорят. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
let's see 0 2 марта, 2013 Опубликовано 2 марта, 2013 · Жалоба void c_copy (void *d, const void *s, uint16_t len) { uint16_t i; uint8_t * dst, *src; dst = d; src = s; for (i = 0; i < len; i++) *dst++ = *src++; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KnightIgor 2 2 марта, 2013 Опубликовано 2 марта, 2013 · Жалоба Так memcpy() отлично проглатывает параметры (void *d, const void *s, uint16_t len), без ошибок. Так что не нужно множить сущности. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
let's see 0 2 марта, 2013 Опубликовано 2 марта, 2013 · Жалоба /* 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. */ ........ Так что не нужно множить сущности. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
PheeL 0 3 марта, 2013 Опубликовано 3 марта, 2013 · Жалоба * If copying takes place between objects that overlap, * the behaviour is undefined. * Returns: the value of s1. */ ........ Конкретно для этого случая есть в наличие тоже стандартная memove(); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
let's see 0 3 марта, 2013 Опубликовано 3 марта, 2013 · Жалоба Конкретно для этого случая есть в наличие тоже стандартная memove(); Нету перекрытия, конкретно не тот случай. Повторяю: проблема в том, что __restrict в определении memcpy не компилируется, когда включен __packed(1) , а без него, компилятор выравнивает структуру, изменяя ее размер, что недопустимо. Вопрос в том, что может ли кто предложить решение эффективней C-copy(). Спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться