[英]Visual C++ generates DIV instead of IDIV (x86, integer arithmetic)
我在这里使用Visual C ++ 2008(9.x),当我遇到生成DIV而不是IDIV的编译器时,我正准备一个固定点值。 我将代码折叠成一小块以完全重现:
short a = -255;
short divisor16 = 640; // unsigned, 16-bit
unsigned int divisor32 = 640; // unsigned, 32-bit
unsigned short s_divisor16 = 640; // signed, 16-bit
int s_divisor32 = 640; // signed, 32-bit
int16_t test1 = (a<<8)/divisor16; // == -102, generates IDIV -> OK
int16_t test2 = (a<<8)/s_divisor16; // == -102, generates IDIV -> OK
int16_t test3 = (a<<8)/divisor32; // == bogus, generates DIV -> FAIL!
int16_t test4 = (a<<8)/s_divisor32; // == -102, generates IDIV -> OK
int bitte_ein_breakpoint=1;
我不会用简单的反汇编来打扰你。
现在不是采用快捷方式而只是改变除数的类型(它是一个函数参数,unsigned int numPixels),我想知道是什么让编译器在第三个(test3)情况下选择DIV而不是IDIV,因为它没有这样做无符号的16位除数,实际上没有任何东西可以调用无符号算术。 至少那是我的想法,我希望我错了:)
为/
运算符生成的代码取决于操作数。
首先,表达式(a << 8)
具有int
类型,因为对每个操作数 (ISO C99,6.5.7p3) 执行整数提升 ,然后操作是int << int
,这导致int
。
现在有四种表达方式:
int / short
:右侧被提升为int
,因此是idiv
指令。 int / unsigned short
:右侧被提升为int
,因此idiv
指令。 int / unsigned int
: 左侧被提升为unsigned int
,因此是div
指令。 int / int
:没有提升,因此idiv
指令是合适的。 整数提升在ISO C99 6.3.1.1p3中定义:
如果
int
可以表示原始类型的所有值,则该值将转换为int
; 否则,它将转换为unsigned int
。 这些被称为整数促销。 。
左移负值会导致未定义的行为。 因此,我不确定您是否可以从编译器在此方案中选择的内容中得出许多结论。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.