вторник, 26 мая 2009 г.

остаток от деления

результатом выполнения кода 65 & 7 будет остаток от деления 65 на 8 = 1. (& - побитовое логическое "И"). В общем случае результат выполнения конструкции a&b равен a%(b+1), где b = 2^n - 1. (% - оператор нахождения остатка от деления левого операнда на правый).
Теоретическая причина по которой конструкция a&b более популярна для нахождения остатка, в том что она исполняется быстрее чем её более понятный для чтения аналог. На практике, последние версии популярных компиляторов в состоянии проводить подобную оптимизацию кода самостоятельно, не говоря уже о том что разница в эффективности исполнения этих двух конструкций вообще не существенна на современных процессорах. В идеале, вы должны знать об этом и других подобных трюках для того чтобы понимать код написанный несколькими годами ранее, но случаи в которых их использование будет оправдано вами в настоящее время действительно встречаются редко.

6 комментариев:

  1. и сейчас применяется. я использовал это при программировании драйвера FAT для AVR :)

    ОтветитьУдалить
  2. а я не говорил что не применяется. я сказал что редко ) программирование МК не слишком популярная ниша, впрочем все относительно.

    ОтветитьУдалить
  3. интересно проверить оптимизирует ли gcc операцию x%y, если y - степень двойки

    ОтветитьУдалить
  4. не оптимизирует!
    [ivaxer@yakudza code-hints]$ diff a.c b.c
    5c5
    < b = 8;
    ---
    > b = 7;
    8c8
    < printf("%d\n", a%b);
    ---
    > printf("%d\n", a&b);
    [ivaxer@yakudza code-hints]$ diff a.s b.s
    1c1
    < .file "a.c"
    ---
    > .file "b.c"
    18c18
    < movl $8, -8(%ebp)
    ---
    > movl $7, -8(%ebp)
    23,27c23,24
    < movl -12(%ebp), %edx
    < movl %edx, %eax
    < sarl $31, %edx
    < idivl -8(%ebp)
    < movl %edx, %eax
    ---
    > movl -12(%ebp), %eax
    > andl -8(%ebp), %eax

    ОтветитьУдалить
  5. с -O3 оптимизирует :P

    [ivaxer@yakudza code-hints]$ diff a.c b.c
    5c5
    < b = 8;
    ---
    > b = 7;
    9c9
    < printf("%d\n", a%b);
    ---
    > printf("%d\n", a&b);
    [ivaxer@yakudza code-hints]$ gcc -S -O3 b.c
    [ivaxer@yakudza code-hints]$ gcc -S -O3 a.c
    [ivaxer@yakudza code-hints]$ diff a.s b.s
    1c1
    < .file "a.c"
    ---
    > .file "b.c"

    P.S. thx4ssh

    ОтветитьУдалить