[英]AVR C hex and dec multiplication not as expected
我剛剛在十六進制整數(例如0xFFFF)與十進制整數(例如2)相乘時,在我的代碼中發現了一個錯誤。 這是出現問題的代碼:
print_int_new_line(0xFFFF*2);
print_int_new_line(65535*2);
執行此代碼會給我以下結果:
65534
131070
這是相關的UART代碼:
void print_int_new_line(uint64_t data) {
print_int(data);
print_new_line();
}
void print_int(uint64_t data) {
char data_buffer[(int)(log(data)+2)]; // size of the number (log(number)+1) + 1 for the /0
ultoa(data, data_buffer, 10); // convert the int to string, base 10
// print the newly created string
print_string(data_buffer);
}
void print_string(char * data) {
// transmit the data char by char
for(; *data != '\0'; data++){
USART_transmit(data);
}
}
void USART_transmit(const char * data){
/* Wait for empty transmit buffer */
while ( !( UCSR0A & (1<<UDRE0)) )
;
/* Put data into buffer, sends the data */
UDR0 = *data;
}
有關我的設置的一些信息:
MCU:ATmega2560電路板:Arduino Mega2560 UART波特率:38400 IDE:Atmel Studio 7.0.4.1417
使用AVR工具鏈。
我在這個 stackoverflow頁面上讀到,在hex和dec int之間可以進行乘法。 此外,在在線 c編譯器中進行測試可以得到正確的輸出。
任何人都可以給我一個解釋嗎?
此行為是由於處理十進制和十六進制整數常量的差異。
對於0xFFFF
和65535
,編譯器將首先嘗試將值轉換為int
。 但由於平台具有16位int
類型,其中INT_MAX
為32767
,因此無法執行該轉換。
關鍵的區別在於下一步。 對於十六進制常量0xFFFF
,編譯器將嘗試將其轉換為unsigned int
,它相當於(unsigned int)65535
。 但是,對於十進制常量,不會嘗試轉換為無符號類型。 下一次轉換嘗試是long int
。 這成功並等同於(long int)65535
。
因此,對print_int_new_line
的調用相當於:
print_int_new_line((unsigned int)65535*2);
print_int_new_line((long int)65535*2);
當2
被提升為乘法時:
print_int_new_line((unsigned int)65535*(unsigned int)2);
print_int_new_line((long int)65535*(long int)2);
第一次乘法的unsigned int
結果太小而無法保存完整結果,因此它被截斷為65534
。 long int
可以保存結果,因此它產生131070
的正確答案。
您可以通過附加L
(即0xFFFFL
)強制十六進制常量來使用long int
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.