[英]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.