繁体   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