在C中,是否可以将一个被除数除以常数并同时得到结果和余数?
我想避免执行2个除法指令,如下例所示:
val=num / 10;
mod=num % 10;
Run Code Online (Sandbox Code Playgroud)
sas*_*ang 14
我不担心指令计数,因为x86指令集将提供一条idivl
指令来计算一条指令中的被除数和余数.任何体面的编译器都会使用此指令.这里的文档http://programminggroundup.blogspot.com/2007/01/appendix-b-common-x86-instructions.html描述了如下指令:
执行无符号除法.将组合的%edx:%eax寄存器中包含的双字的内容除以指定的寄存器或存储单元中的值.%eax寄存器包含结果商,%edx寄存器包含结果余数.如果商太大而不适合%eax,则会触发类型0中断.
例如,编译此示例程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int x = 39;
int divisor = 1;
int div = 0;
int rem = 0;
printf("Enter the divisor: ");
scanf("%d", &divisor);
div = x/divisor;
rem = x%divisor;
printf("div = %d, rem = %d\n", div, rem);
}
Run Code Online (Sandbox Code Playgroud)
使用gcc -S -O2(-S保存创建的显示asm列表的临时文件),显示以下行中的除法和mod
div = x/divisor;
rem = x%divisor;
Run Code Online (Sandbox Code Playgroud)
有效地减少到以下指令:
idivl 28(%esp)
Run Code Online (Sandbox Code Playgroud)
正如您可以看到执行除法和mod计算的一条指令.在idivl
即使MOD计算在C程序被移除指令保持.之后idivl
有电话mov
:
movl $.LC2, (%esp)
movl %edx, 8(%esp)
movl %eax, 4(%esp)
call printf
Run Code Online (Sandbox Code Playgroud)
这些调用将商和余数复制到堆栈上以调用printf.
有趣的div
是,除了在函数调用中包装/和%运算符之外,该函数没有做任何特殊操作.因此,从性能的角度来看,它不会通过替换线来改善性能
val=num / 10;
mod=num % 10;
Run Code Online (Sandbox Code Playgroud)
只需一个电话div
.
有div():
div_t result = div(num, 10);
// quotient is result.quot
// remainder is result.rem
Run Code Online (Sandbox Code Playgroud)