|
вопрос по memcpy |
|
|
|
Dec 2 2015, 07:16
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
функция копирует с младшего байта в младший байт. а нельзя как нибудь начиная со старшего байта в младший байт? то есть сейчас Код dest[] = {0} src[] = {1,2,3,4,5} memcpy(dest,src,5); и после выполнения Код dest = {1,2,3,4,5} а я хочу Код dest = {5,4,3,2,1}
|
|
|
|
3 страниц
1 2 3 >
|
 |
Ответов
(1 - 33)
|
Dec 2 2015, 08:58
|

Местный
  
Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502

|
Цитата(Jenya7 @ Dec 2 2015, 08:50)  то есть надо переворачивать исходный массив? а есть какой нибудь быстрый алгоритм перевернуть или ничего нового не придумали? А обязательно гонять данные по массиву туда-сюда ? Можно ли просто обращаться к его этементам в обратном порядке ? Быстрый алгоритм можно придумать для каких-нибудь частных случаев, типа только 4 элемента по байту каждый, учесть влияние кэша процессора итп.
|
|
|
|
|
Dec 2 2015, 09:01
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(CrimsonPig @ Dec 2 2015, 14:58)  А обязательно гонять данные по массиву туда-сюда ? Можно ли просто обращаться к его этементам в обратном порядке ? Быстрый алгоритм можно придумать для каких-нибудь частных случаев, типа только 4 элемента по байту каждый, учесть влияние кэша процессора итп. тоже вариант нет. функция посылки тоже начинает с младшего байта. лучше сразу перевернуть, быстрее будет. Код void ReverseArray(uint8_t *dest, uint8_t *src, uint32_t size) { int i,j; for (i = (size - 1), j = 0; i >= 0; i--, j++) dest[j] = src[i]; }
Сообщение отредактировал Jenya7 - Dec 2 2015, 09:05
|
|
|
|
|
Dec 2 2015, 09:17
|

Местный
  
Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502

|
Цитата(Jenya7 @ Dec 2 2015, 09:01)  Код void ReverseArray(uint8_t *dest, uint8_t *src, uint32_t size) { int i,j; for (i = (size - 1), j = 0; i >= 0; i--, j++) dest[j] = src[i]; } За такой код на code review коллеги сходу бьют ссаными тряпками  - что будет, если аргумент size по какой-либо причине будет 0 ? - аргумент src должен быть const uint8_t* - аргумент dest желательно объявлять как void*
|
|
|
|
|
Dec 2 2015, 09:32
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(CrimsonPig @ Dec 2 2015, 15:17)  За такой код на code review коллеги сходу бьют ссаными тряпками  - что будет, если аргумент size по какой-либо причине будет 0 ? я не имею такой роскоши обложить асертами все аргументы  Цитата(CrimsonPig @ Dec 2 2015, 15:17)  - аргумент src должен быть const uint8_t* ну затрут его, не жалко  Цитата(CrimsonPig @ Dec 2 2015, 15:17)  - аргумент dest желательно объявлять как void* я за строгую типизацию, сэйф код
|
|
|
|
|
Dec 2 2015, 09:35
|

Местный
  
Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502

|
Цитата(Jenya7 @ Dec 2 2015, 09:32)  я не имею такой роскоши обложить асертами все аргументы  ну затрут его, не жалко  я за строгую типизацию, сэйф код  Стандартные отмазки говнокодера. код: if(!aSize) { assert(0); return; } не стоит практически ничего. остальное даже комментировать не имеет смысла.
|
|
|
|
|
Dec 2 2015, 10:31
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (CrimsonPig @ Dec 2 2015, 12:26)  когда в паре тысяч выпущенных в продажу девайсов такие куски кода для внутреннего употребления начнут затирать чужую память... Это если их будет вызывать говнокодер. Ну и никакие assert и иже с ними не позволят вдруг сделать написанный говнокодером код рабочим. Как он НЕ работал правильно, допустим, затирая, кусок памяти, так он не будет работать ничего не делая или вылетая на assert. И не надо мне тут про тысячи, например, выпущенных в продажу кофемолок - ну не поможет никакой assert разобраться с говнокодом на кухне у конечного потребителя. По этой причине я и написал - "борьба говнокодера с говнокодом за право говнокодировать".
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Dec 2 2015, 10:55
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(smalcom @ Dec 2 2015, 13:45)  Да, осталось pDestArr сделать void const *, а pSrcArr сделать void *. Чтобы этой функцией можно было переворачивать любые данные, в том числе лежащие во флеше. И do { } while(--pSize) заменить на while(pSize--) {} выкинув еще одно условие и упростив исходник. После чего перейти на Си с плюсами, написав шаблон-обертку, следящую за тем, чтобы pDestArr и pSrcArr указывали на одинаковый тип.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 2 2015, 11:12
|

Местный
  
Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502

|
Цитата(Сергей Борщ @ Dec 2 2015, 10:55)  Да, осталось pDestArr сделать void const *, а pSrcArr сделать void *. Чтобы этой функцией можно было переворачивать любые данные, в том числе лежащие во флеше. И do { } while(--pSize) заменить на while(pSize--) {} выкинув еще одно условие и упростив исходник. После чего перейти на Си с плюсами, написав шаблон-обертку, следящую за тем, чтобы pDestArr и pSrcArr указывали на одинаковый тип. Щаз вам очередной великий кодер скажет, что использовать void* некошерно, потому что правильные программисты (они не пишут ассертов, да) должны заранее знать тип передаваемого значения в функцию memcpy
|
|
|
|
|
Dec 2 2015, 11:18
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(CrimsonPig @ Dec 2 2015, 14:12)  должны заранее знать тип передаваемого значения в функцию memcpy  memcopy как раз имеет аргументы void const * и void *. Некторые знают, что это сделано специально для использования неявного приведения типов.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 2 2015, 11:55
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(Jenya7 @ Dec 2 2015, 14:46)  вылетает ошибка invalid use of void expression Где вылетает? Телепатирую: внутри функции. Я писал "что" надо сделать, а не "как". Ладно, читайте по губам: Код void ReverseArray(void * pDestArr, void const * pSrcArr, size_t size) { uint8_t const * from = (uint8_t const *)pSrcArr; uint8_t * to = (uint8_t *)pDstArr + size - 1;
while(size --) *to-- = *from++; }
void test() { char Result[50]; ReverseArray(Result, "Слава мне, победителю драконов!", sizeof("Слава мне, победителю драконов!")); }
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 2 2015, 12:37
|

Местный
  
Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502

|
Цитата(Сергей Борщ @ Dec 2 2015, 11:55)  Где вылетает? Телепатирую: внутри функции. Я писал "что" надо сделать, а не "как". Ладно, читайте по губам: [code]void ReverseArray(void * pDestArr, void const * pSrcArr, size_t size) Кстати, я бы смотрел на мир ширше. Тут IMHO либо надо явно указать, что функция реверсирует _байты_ в массиве (и тогда использовать явный тип указателей, void* в этом случае, наверное не имеет смысла), либо передавать void* и размер элемента массива заодно.. А то получается некая неопределенность. E.g. void CopyArray_ReverseBytes(uint8_t* apDest, const uint8_t* apSrc, size_t aNumBytes); void CopyArray_Reverse(void* apDest, const void* apSrc, size_t aElemSize, size_t aNumElements);
|
|
|
|
|
Dec 2 2015, 13:02
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(Сергей Борщ @ Dec 2 2015, 17:55)  Где вылетает? Телепатирую: внутри функции. Я писал "что" надо сделать, а не "как". Ладно, читайте по губам: Код void ReverseArray(void * pDestArr, void const * pSrcArr, size_t size) { uint8_t const * from = (uint8_t const *)pSrcArr; uint8_t * to = (uint8_t *)pDstArr + size - 1;
while(size --) *to-- = *from++; }
void test() { char Result[50]; ReverseArray(Result, "Слава мне, победителю драконов!", sizeof("Слава мне, победителю драконов!")); } я понял. но аргумент можно привести к нужному типу и вне функции. если понадобиться.
|
|
|
|
|
Dec 2 2015, 13:07
|

Профессионал
    
Группа: Свой
Сообщений: 1 292
Регистрация: 26-06-07
Пользователь №: 28 718

|
Цитата do { } while(--pSize) заменить на while(pSize--) {} идите в отдел кадров. скажите, что вы уже некомпетентны. Цитата Щаз вам очередной великий кодер скажет uint8_t - "простейшее". С ним удобна математика указателей. Можно использовать void*, но в теле тогда уже, либо использовать сумбурную запись с приведением типов, либо локально объявить нужные указатели. Вы определитесь уже в своей толпе. Ато один размер сокращает, второй умничает... Хотите напыщенно позвенеть яйцами - вперёд в онлайн тесты по C/C++. Хоть больше "удовлетворительно" наберите. Цитата size_t не может быть меньше нуля это знаковый тип, т.к. используется и для возвращения кода ошибки.
|
|
|
|
|
Dec 2 2015, 14:59
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(Jenya7 @ Dec 2 2015, 16:02)  я понял. но аргумент можно привести к нужному типу и вне функции. если понадобится. В почти каждой точке вызова? Вы правда считаете, что засорение исходников такими приведениями типа лучше, чем одно приведение, спрятанное в теле функции? Ваше право. Успехов в сопровождении таких исходников! Цитата(smalcom @ Dec 2 2015, 16:07)  идите в отдел кадров. скажите, что вы уже некомпетентны. А теперь посмотрите на исходник, к котрому это относилось или прочитайте до конца: "выкинув еще одно условие и упростив исходник". Условие, которое было перед циклом. Если вы докажете, что результат работы изначального исходника и моего кода с while(pSize--) {} отличается - схожу.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 2 2015, 16:06
|

Местный
  
Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502

|
Цитата(Mahagam @ Dec 2 2015, 15:20)  а как любители ассертов ассертят то, что src и dst могут в памяти перекрываться? для всех остальных, умеющих программировать, кроме memcpy есть и memmove. Хе, я хотел написать, что я бы еще проверял, что src & dest не равны и не перекрываются, но побоялся справедливого гнева настоящих кодеров, которые ассерты не используют. а в чем проблемы-то ? адреса известны, размер буфера тоже. Массивы по определению непрерывны.
|
|
|
|
|
Dec 3 2015, 00:24
|

Профессионал
    
Группа: Свой
Сообщений: 1 292
Регистрация: 26-06-07
Пользователь №: 28 718

|
Исходник Код int main() { volatile int ps1 = 1; volatile int cnt = 0;
#if 0 while(ps1--) { cnt++; printf("%i, %i", cnt, ps1); } #else if(ps1 > 0) { do { cnt++; printf("%i, %i", cnt, ps1); } while(--ps1); } #endif
return 0; } Для while{} Код 00000000 <main>: 0: e3a02001 mov r2, #1 4: e3a03000 mov r3, #0 8: e52de004 push {lr} ; (str lr, [sp, #-4]!) c: e24dd00c sub sp, sp, #12 10: e58d2000 str r2, [sp] 14: e58d3004 str r3, [sp, #4]
18: ea000006 b 38 <main+0x38>
1c: e59d3004 ldr r3, [sp, #4] 20: e2833001 add r3, r3, #1 24: e58d3004 str r3, [sp, #4]
28: e59d1004 ldr r1, [sp, #4] 2c: e59f0028 ldr r0, [pc, #40] ; 5c <main+0x5c> 30: e59d2000 ldr r2, [sp] 34: ebfffffe bl 0 <printf>
38: e59d3000 ldr r3, [sp] 3c: e3530000 cmp r3, #0 40: e2433001 sub r3, r3, #1 44: e58d3000 str r3, [sp] 48: 1afffff3 bne 1c <main+0x1c>
4c: e3a00000 mov r0, #0 50: e28dd00c add sp, sp, #12 54: e49de004 pop {lr} ; (ldr lr, [sp], #4) 58: e12fff1e bx lr 5c: 00000000 .word 0x00000000 Для do {} while() Код 00000000 <main>: 0: e3a03000 mov r3, #0 4: e3a02001 mov r2, #1 8: e52de004 push {lr} ; (str lr, [sp, #-4]!) c: e24dd00c sub sp, sp, #12 10: e58d2000 str r2, [sp] 14: e58d3004 str r3, [sp, #4]
18: e59d3000 ldr r3, [sp] 1c: e3530000 cmp r3, #0 20: da00000b ble 54 <main+0x54>
24: e59d3004 ldr r3, [sp, #4] 28: e2833001 add r3, r3, #1 2c: e58d3004 str r3, [sp, #4]
30: e59d1004 ldr r1, [sp, #4] 34: e59f0028 ldr r0, [pc, #40] ; 64 <main+0x64> 38: e59d2000 ldr r2, [sp] 3c: ebfffffe bl 0 <printf> 40: e59d3000 ldr r3, [sp] 44: e2433001 sub r3, r3, #1 48: e3530000 cmp r3, #0 4c: e58d3000 str r3, [sp] 50: 1afffff3 bne 24 <main+0x24>
54: e3a00000 mov r0, #0 58: e28dd00c add sp, sp, #12 5c: e49de004 pop {lr} ; (ldr lr, [sp], #4) 60: e12fff1e bx lr 64: 00000000 .word 0x00000000 Компилятор gcc-5.2.0. Сборка arm-none-eabi-gcc -c 1.c -O2 -o 0.o Что говорит букварь Код if() <- проверка - один раз; переход один раз в плохом случае do ... while <- проверка и переход каждую итерацию Код while <- проверка - каждую итерацию, переход - один раз в конце { ... } <- переход каждую итерацию для while всегда имеем +1 переход Цитата но побоялся справедливого гнева настоящих кодеров, которые ассерты не используют. программа, по воможности, должна работать при любых ошибках. assert - это аварийное завершение. по сути перекладывание проблемы с разработчика на пользователя. когда запускаешь программу и видишь аварийный выход из-за какой-то ерунды во входных параметрах, хочется испепелить разработчика, который не осилил правильную передачу вверх ошибки или использование исключения.
|
|
|
|
|
Dec 3 2015, 03:58
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(smalcom @ Dec 3 2015, 06:24)  программа, по воможности, должна работать при любых ошибках. assert - это аварийное завершение. по сути перекладывание проблемы с разработчика на пользователя. когда запускаешь программу и видишь аварийный выход из-за какой-то ерунды во входных параметрах, хочется испепелить разработчика, который не осилил правильную передачу вверх ошибки или использование исключения. Вы предлагаете не использовать assert-ы и тупо виснуть в случае неверных аргументов??? Странный подход...... Вообще-то - assert - это проверка входных условий функций. И используется как раз для отладки, для того, чтобы на стадии разработки и отладки выявить случаи передачи неверных аргументов. Если этот assert возникает у юзера, это проблема не assert-а, а проблема в недостаточной отлаженности ПО. И даже в этом случае лучше пусть выполнится действие заложенное по assert (аварийный выход или там чего), чем это ПО повиснет.
|
|
|
|
|
Dec 3 2015, 13:25
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(smalcom @ Dec 3 2015, 03:24)  Исходник Код volatile int ps1 = 1; volatile int cnt = 0; Это наглый мухлеж. С тем же успехом можно было отключить оптимизацию. Незачет.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|