优化会改变强制转换的行为吗?

Does optimization change the behavior of casts?

我正在使用小型 UART 设备,经常需要切换其运行的波特率。
基本上整个设置归结为

#define FOSC 2000000
#define BAUD 9600

uint8_t rate = (uint8_t) ((FOSC / (16.0 * BAUD)) - 1 + 0.5);

(其中 +0.5 用于对结果进行四舍五入。)

我目前正在使用 gcc 4.8.1 进行编译,-O1
编译器是否优化了整个转换,或者我只剩下一个转换后跟一个常量?不同的 -O# 值(-O0 除外)会有所不同吗? -Os 怎么样(我最终可能不得不用它来编译)?

如果重要的话,我正在开发 Atmel AT90USB647 (or the datasheet [pdf])。

在启用优化的情况下进行编译时,极有可能任何理智的编译器会将整个表达式(包括转换)转换为常量。

但是,为了确定,您需要查看编译器的汇编输出。

但是特别是 GCC 4.8.1 呢?

代码

#include <stdint.h>
#include <stdio.h>

#define FOSC 2000000
#define BAUD 9600

int main() {
    uint8_t rate = (uint8_t) (FOSC / (16.0 * BAUD)) - 1 + 0.5;
    printf("%u", rate);
}

生成的程序集的一部分 gcc -O1 red.c

main:
.LFB11:
    .cfi_startproc
    subq    , %rsp
    .cfi_def_cfa_offset 16
    movl    , %esi
    movl    $.LC0, %edi
    movl    [=11=], %eax
    call    printf

我们可以清楚地看到gcc已经为rate.

预先计算了12的值

Atmel AVR 发布 newlib C 库,它是一个简单的 ANSI C 库、数学库和电路板支持包的集合。您可以参考 ANSI C 规范来了解。特别是转换部分。

我会确保将速率写入可变变量或指针。也许速率值计算正常,但是当它写入外围目的地时它缺少易失性标记并且优化器不执行写入操作。