Jump to content

    

отследить изменение переменной.

и все это для того чтобы сравнить неколько переменных? мне кажется быстрее уж сделать тем же memcmp

Ну и каша у Вас с голове :(. Рано Вам реальным программирванием заниматься :( если не понимаете разницы между преобразованиями типов данных и работой данными. "Все это" НИ ОДНОГО БИТА КОДА НЕ ДОБАВЛЯЕТ. "Вcе это" только ИНСТУКЦИИ компилятору, как ему МАКСИМАЛЬНО эффективно сделать работу при ОНОВРЕМЕННОМ обеспечении читаемомти человеком.

Share this post


Link to post
Share on other sites
и все это для того чтобы сравнить неколько переменных? мне кажется быстрее уж сделать тем же memcmp

 

Программа пишется не для компилятора, а в первую очередь для того, кто будет её читать в будущем. Возможно и для будущего вас.

Share this post


Link to post
Share on other sites
а что можно прямо так ?

(my_struct *) my_arr

Да, конечно. Преобразование типа говорящее компилятору, что там по указателю на самом деле не свалка байтов, а структура. В структуре находися какая-то 32 bit переменая. Осталось только сказать компилятору что бы взял эту переменную.

 

((my_struct *) my_arr)->value_32bit

 

И сделает от это МАСИМАЛЬНО эффективным способом.

Для человеческой читабельности можно спрятать преобразование в макрос, или промежуточную переменную, которую компилятор все равно заоптимизирует.

Получится типа:

 

my_struct->value_32bit

Share this post


Link to post
Share on other sites

понял.спасибо.

Edited by Herz
Избыточное цитирование

Share this post


Link to post
Share on other sites

сделал листинг ради интереса.

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

нехилая разница.

Edited by Jenya7

Share this post


Link to post
Share on other sites
можно заменить на

Не можно, а НУЖНО. Нужно давать компилятору нормальные максимально обобщенные задания а не заставлять его жонглировать байтами и битами. Грубо говоря надо стараться давать задание "выкопай яму", а не "возьми лопату, воткни в землю, бери больше, кидай дальше...повтори...". Для этого надо в первую очередь знать язык, ибо на подмножестве языка уровня Эллочки Людоедки, объяснить компилятору нормально не реально.

 

Share this post


Link to post
Share on other sites
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, а так да, оно рулит :)

 

 

Share this post


Link to post
Share on other sites
На ARM этот 'частный случай' даст hard fault...

Не обязательно fault - чаще фигню взятую по выровненному адресу молча возвратит. Зависит от конкретной реализации в ядре сделанной конкретным производителем чипа. Но то, что получится нерабочий код это точно.

 

Share this post


Link to post
Share on other sites
Не обязательно fault - чаще фигню взятую по выровненному адресу молча возвратит. Зависит от конкретной реализации в ядре сделанной конкретным производителем чипа. Но то, что получится нерабочий код это точно.

 

Таки коллективный разум все еще считает себя умнее и быстрее правильно заинлайненного memcmp ? :)

Share this post


Link to post
Share on other sites
:)

К чему эта улыбочка? Для начала попробуйте сделать этот самый "правильно заинлайненый". Для начала этого сделать просто не удастся - это библиотечная функция. Посему посморите просто на исходник memcmp() дабы, даже если ее заинлайтить, понять написанную Вами глупость.

 

Share this post


Link to post
Share on other sites
К чему эта улыбочка? Для начала попробуйте сделать этот самый "правильно заинлайненый". Для начала этого сделать просто не удастся - это библиотечная функция. Посему посморите просто на исходник 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

Edited by CrimsonPig

Share this post


Link to post
Share on other sites
Для начала попробуйте сделать этот самый "правильно заинлайненый". Для начала этого сделать просто не удастся - это библиотечная функция.
Не всегда - у gcc например это может быть intrinsic функция компилятора (если ему включить оптимизацию, конечно)

 

 

 

Share this post


Link to post
Share on other sites
Не всегда - у 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

 

 

Share this post


Link to post
Share on other sites
Договорились. Пререходим к следующему шагу - используем GCC и его intrinsic, получаем результат и сравниваем с:

 

memcmp - то гарантированно работает с невыравненными данными.

Если есть 100% гарантия, что данные выравнены, то и заинлайненная memcmp из библиотеки будет на 3 инструкции.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this