簡體   English   中英

AVR C十六進制和十進制乘法不如預期

[英]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編譯器中進行測試可以得到正確的輸出。

任何人都可以給我一個解釋嗎?

此行為是由於處理十進制和十六進制整數常量的差異。

對於0xFFFF65535 ,編譯器將首先嘗試將值轉換為int 但由於平台具有16位int類型,其中INT_MAX32767 ,因此無法執行該轉換。

關鍵的區別在於下一步。 對於十六進制常量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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM