zltigo 0 15 декабря, 2015 Опубликовано 15 декабря, 2015 · Жалоба и все это для того чтобы сравнить неколько переменных? мне кажется быстрее уж сделать тем же memcmp Ну и каша у Вас с голове :(. Рано Вам реальным программирванием заниматься :( если не понимаете разницы между преобразованиями типов данных и работой данными. "Все это" НИ ОДНОГО БИТА КОДА НЕ ДОБАВЛЯЕТ. "Вcе это" только ИНСТУКЦИИ компилятору, как ему МАКСИМАЛЬНО эффективно сделать работу при ОНОВРЕМЕННОМ обеспечении читаемомти человеком. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
msalov 0 15 декабря, 2015 Опубликовано 15 декабря, 2015 · Жалоба и все это для того чтобы сравнить неколько переменных? мне кажется быстрее уж сделать тем же memcmp Программа пишется не для компилятора, а в первую очередь для того, кто будет её читать в будущем. Возможно и для будущего вас. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 15 декабря, 2015 Опубликовано 15 декабря, 2015 · Жалоба а что можно прямо так ? (my_struct *) my_arr Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 0 15 декабря, 2015 Опубликовано 15 декабря, 2015 · Жалоба а что можно прямо так ? (my_struct *) my_arr Да, конечно. Преобразование типа говорящее компилятору, что там по указателю на самом деле не свалка байтов, а структура. В структуре находися какая-то 32 bit переменая. Осталось только сказать компилятору что бы взял эту переменную. ((my_struct *) my_arr)->value_32bit И сделает от это МАСИМАЛЬНО эффективным способом. Для человеческой читабельности можно спрятать преобразование в макрос, или промежуточную переменную, которую компилятор все равно заоптимизирует. Получится типа: my_struct->value_32bit Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 15 декабря, 2015 Опубликовано 15 декабря, 2015 (изменено) · Жалоба понял.спасибо. Изменено 17 декабря, 2015 пользователем Herz Избыточное цитирование Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 16 декабря, 2015 Опубликовано 16 декабря, 2015 (изменено) · Жалоба сделал листинг ради интереса. if (new_packet[4] != old_packet[4] || new_packet[5] != old_packet[5] || new_packet[6] != old_packet[6] || new_packet[7] != old_packet[7]) 1db8: 7938 ldrb r0, [r7, #4] 1dba: 7933 ldrb r3, [r6, #4] 1dbc: 4298 cmp r0, r3 1dbe: d10b bne.n 1dd8 <PARSER_ParseBlePacket+0x458> 1dc0: 797a ldrb r2, [r7, #5] 1dc2: 7971 ldrb r1, [r6, #5] 1dc4: 428a cmp r2, r1 1dc6: d107 bne.n 1dd8 <PARSER_ParseBlePacket+0x458> 1dc8: 79bd ldrb r5, [r7, #6] 1dca: 79b0 ldrb r0, [r6, #6] 1dcc: 4285 cmp r5, r0 1dce: d103 bne.n 1dd8 <PARSER_ParseBlePacket+0x458> 1dd0: 79fa ldrb r2, [r7, #7] 1dd2: 79f3 ldrb r3, [r6, #7] 1dd4: 429a cmp r2, r3 1dd6: d010 beq.n 1dfa <PARSER_ParseBlePacket+0x47a> if(*((uint32_t*)&new_packet[4]) != *((uint32_t*)&old_packet[4])) 1db8: 6878 ldr r0, [r7, #4] 1dba: 6873 ldr r3, [r6, #4] 1dbc: 4298 cmp r0, r3 1dbe: d010 beq.n 1de2 <PARSER_ParseBlePacket+0x462> if(memcmp(&new_packet[4],&old_packet[4],4) != 0) 1a48: 1d3c adds r4, r7, #4 1a4a: 4620 mov r0, r4 1a4c: 1d31 adds r1, r6, #4 1a4e: 2204 movs r2, #4 1a50: f005 f8f8 bl 6c44 <memcmp> 1a54: b160 cbz r0, 1a70 <PARSER_ParseBlePacket+0xf0> if(*((uint32_t*)&new_packet[4]) != *((uint32_t*)&old_packet[4])) рулит. в принципе это частный случай более общего - ((my_struct *) my_arr)->value_32bit кстати я тут подумал такую запись tempParam.maxFlowRate = (uint32_t)new_packet[0]+((uint32_t)new_packet[1]<<8)+((uint32_t)new_packet[2]<<16)+((uint32_t)new_packet[3]<<24); можно заменить на tempParam.maxFlowRate = *((uint32_t*)&new_packet[0]); или tempParam.maxFlowRate = ((my_struct *) my_arr)->value_32bit или я не прав? вот листинг tempParam.maxFlowRate = (uint32_t)new_packet[3]+((uint32_t)new_packet[2]<<8)+((uint32_t)new_packet[1]<<16)+((uint32_t)new_packet[0]<<24); 1e32: 7878 ldrb r0, [r7, #1] 1e34: 78bc ldrb r4, [r7, #2] 1e36: 0403 lsls r3, r0, #16 1e38: 78fa ldrb r2, [r7, #3] 1e3a: eb03 2104 add.w r1, r3, r4, lsl #8 1e3e: 7838 ldrb r0, [r7, #0] 1e40: 188c adds r4, r1, r2 1e42: eb04 6300 add.w r3, r4, r0, lsl #24 1e46: 9317 str r3, [sp, #92]; 0x5c tempParam.maxFlowRate = *((uint32_t*)&new_packet[0]); 1998: 683b ldr r3, [r7, #0] 199c: 9317 str r3, [sp, #92]; 0x5c нехилая разница. Изменено 16 декабря, 2015 пользователем Jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 0 16 декабря, 2015 Опубликовано 16 декабря, 2015 · Жалоба можно заменить на Не можно, а НУЖНО. Нужно давать компилятору нормальные максимально обобщенные задания а не заставлять его жонглировать байтами и битами. Грубо говоря надо стараться давать задание "выкопай яму", а не "возьми лопату, воткни в землю, бери больше, кидай дальше...повтори...". Для этого надо в первую очередь знать язык, ибо на подмножестве языка уровня Эллочки Людоедки, объяснить компилятору нормально не реально. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xvr 12 16 декабря, 2015 Опубликовано 16 декабря, 2015 · Жалоба if(*((uint32_t*)&new_packet[4]) != *((uint32_t*)&old_packet[4])) рулит. в принципе это частный случай более общего - ((my_struct *) my_arr)->value_32bitНа ARM этот 'частный случай' даст hard fault если адрес new_packet или old_packet не будет кратен 4, а так да, оно рулит :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 0 16 декабря, 2015 Опубликовано 16 декабря, 2015 · Жалоба На ARM этот 'частный случай' даст hard fault... Не обязательно fault - чаще фигню взятую по выровненному адресу молча возвратит. Зависит от конкретной реализации в ядре сделанной конкретным производителем чипа. Но то, что получится нерабочий код это точно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
CrimsonPig 0 16 декабря, 2015 Опубликовано 16 декабря, 2015 · Жалоба Не обязательно fault - чаще фигню взятую по выровненному адресу молча возвратит. Зависит от конкретной реализации в ядре сделанной конкретным производителем чипа. Но то, что получится нерабочий код это точно. Таки коллективный разум все еще считает себя умнее и быстрее правильно заинлайненного memcmp ? :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 0 16 декабря, 2015 Опубликовано 16 декабря, 2015 · Жалоба :) К чему эта улыбочка? Для начала попробуйте сделать этот самый "правильно заинлайненый". Для начала этого сделать просто не удастся - это библиотечная функция. Посему посморите просто на исходник memcmp() дабы, даже если ее заинлайтить, понять написанную Вами глупость. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
CrimsonPig 0 16 декабря, 2015 Опубликовано 16 декабря, 2015 (изменено) · Жалоба К чему эта улыбочка? Для начала попробуйте сделать этот самый "правильно заинлайненый". Для начала этого сделать просто не удастся - это библиотечная функция. Посему посморите просто на исходник memcmp() дабы, даже если ее заинлайтить, понять написанную Вами глупость. Я делаю так: 1. пишу memcmp 2. компилирую в release c соответствующими опциями оптимизации. 3. все Например, такая вот глупая функция: int Foo_cmp(const void* apSrc, size_t aNumBytes) { unsigned char buf[100] = "abcdef"; return memcmp(apSrc, buf, aNumBytes); } компилируется в следующий кусок ассемблерной хрени: return memcmp(apSrc, buf, aNumBytes); 0134103E mov esi,0Fh 01341043 lea ecx,[ebp-68h] 01341046 mov edx,offset string "qweqweqweq" (13420FCh) 0134104B jmp Foo_cmp+50h (1341050h) 0134104D lea ecx,[ecx] 01341050 mov eax,dword ptr [edx] 01341052 cmp eax,dword ptr [ecx] 01341054 jne Foo_cmp+68h (1341068h) 01341056 sub esi,4 01341059 add ecx,4 0134105C add edx,4 0134105F cmp esi,4 01341062 jae Foo_cmp+50h (1341050h) 01341064 test esi,esi 01341066 je Foo_cmp+0B9h (13410B9h) 01341068 movzx eax,byte ptr [edx] 0134106B movzx edi,byte ptr [ecx] 0134106E sub eax,edi 01341070 jne Foo_cmp+0A3h (13410A3h) 01341072 cmp esi,1 01341075 jbe Foo_cmp+0B9h (13410B9h) 01341077 movzx eax,byte ptr [edx+1] 0134107B movzx edi,byte ptr [ecx+1] 0134107F sub eax,edi 01341081 jne Foo_cmp+0A3h (13410A3h) 01341083 cmp esi,2 01341086 jbe Foo_cmp+0B9h (13410B9h) 01341088 movzx eax,byte ptr [edx+2] 0134108C movzx edi,byte ptr [ecx+2] 01341090 sub eax,edi 01341092 jne Foo_cmp+0A3h (13410A3h) 01341094 cmp esi,3 01341097 jbe Foo_cmp+0B9h (13410B9h) 01341099 movzx eax,byte ptr [edx+3] 0134109D movzx ecx,byte ptr [ecx+3] 013410A1 sub eax,ecx 013410A3 sar eax,1Fh 013410A6 pop edi 013410A7 or eax,1 013410AA pop esi В debug версии да, стоит честный вызов memcmp Изменено 16 декабря, 2015 пользователем CrimsonPig Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xvr 12 16 декабря, 2015 Опубликовано 16 декабря, 2015 · Жалоба Для начала попробуйте сделать этот самый "правильно заинлайненый". Для начала этого сделать просто не удастся - это библиотечная функция.Не всегда - у gcc например это может быть intrinsic функция компилятора (если ему включить оптимизацию, конечно) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 0 16 декабря, 2015 Опубликовано 16 декабря, 2015 · Жалоба Не всегда - у gcc например это может быть intrinsic функция компилятора (если ему включить оптимизацию, конечно) Договорились. Пререходим к следующему шагу - используем GCC и его intrinsic, получаем результат и сравниваем с: if(*((uint32_t*)&new_packet[4]) != *((uint32_t*)&old_packet[4])) 1db8: 6878 ldr r0, [r7, #4] 1dba: 6873 ldr r3, [r6, #4] 1dbc: 4298 cmp r0, r3 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
CrimsonPig 0 16 декабря, 2015 Опубликовано 16 декабря, 2015 · Жалоба Договорились. Пререходим к следующему шагу - используем GCC и его intrinsic, получаем результат и сравниваем с: memcmp - то гарантированно работает с невыравненными данными. Если есть 100% гарантия, что данные выравнены, то и заинлайненная memcmp из библиотеки будет на 3 инструкции. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться