保证uint8_t小于9

时间:2015-10-07 08:38:37

标签: c

我想保证无符号值小于9而没有分支且没有模运算符(要求): 模数为

的算法
x  = x % 9

带循环/分支的算法:

while(x >= 9)
{
  x -= 9;
}

在特殊情况下(如阈值== 8),可以通过以下方式实现:

x = x & 0x07u;

阈值是否有可能等于9?

3 个答案:

答案 0 :(得分:3)

我不明白为什么要替换模运算符。 如果是效率,请考虑以下两个示例:

int main(int argc, char* argv[]) {
  int x  = argc % 9;
  return x;
}

int main(int argc, char* argv[]) {
  int x = argc - (argc / 9) * 9;
  return x;
}

对于这两个实现,gcc -g -O3正在生成相同的程序集(我在x86上使用gcc 4.8.1):

main:
    movl    %edi, %eax  # argc, tmp71
    movl    $954437177, %edx    #, tmp65
    imull   %edx    # tmp65
    movl    %edi, %eax  # argc, tmp67
    sarl    $31, %eax   #, tmp67
    sarl    %edx    # x
    subl    %eax, %edx  # tmp67, x
    leal    (%rdx,%rdx,8), %eax #, tmp70
    subl    %eax, %edi  # tmp70, x
    movl    %edi, %eax  # x,
    ret

结论:不关心效率(在这种情况下和大多数情况下),让编译器这样做。

顺便说一句:954437177(2^33 + 1) / 9

答案 1 :(得分:3)

这就是编译器的用途。输入生成所需输出的代码,编译器生成最有效的程序集以生成该输出。

实际上,C语言是根据抽象机器定义的,其中只定义了其可观察行为。

对于该计划:

int main(int x, char **z)
{ 
    x  = x % 9;
    return x;
}

gcc 5.2 -O3生成:

main:
    movl    %edi, %eax
    movl    $954437177, %edx
    imull   %edx
    movl    %edx, %eax
    movl    %edi, %edx
    sarl    %eax
    sarl    $31, %edx
    subl    %edx, %eax
    leal    (%rax,%rax,8), %eax
    subl    %eax, %edi
    movl    %edi, %eax
    ret

我不确定这是什么,但954437177是0b00111000111000111000111000111001。如果你有兴趣,或许你可以将这个程序集与你手工提出的任何其他东西进行对比。

答案 2 :(得分:1)

你可以使用这个方法,没有循环,分支或模数:

#include <stdio.h>
#include <stdint.h>

int main(void)
{
    uint8_t x = 15; 
    printf("%u", x - (x/9)*9);
    return 0;
}

节目输出:

6