C Actor : Is this expression coded correctly?

标签 c casting

我继承了一些使用 elm-chaN fatfs 的代码。它创建的目录和文件缺少或错误的日期时间戳。我已将问题追溯到似乎不正确的转换。

我更换了 Actor 阵容,一切似乎都顺利。但我希望更有经验的程序员确认原始转换的构造不正确(或编译器问题)

下面是原始代码:curTime 结构将 uint16_t 分配给“Year”。其他成员是 uint8_t 类型。它们需要按照 DOS 日期/时间位图格式打包成 32b 字 (DWORD)。

{
    DWORD tmr;

    /* Pack date and time into a DWORD variable */
    Calendar curTime = sdInterface->sdGetRTCTime();

    tmr = ((DWORD)(curTime.Year-1980)<<25)
            | ((DWORD)(curTime.Month) << 21)
            | ((DWORD)(curTime.DayOfMonth) << 16)
            | (curTime.Hours << 11)
            | (curTime.Minutes << 5)
            | (curTime.Seconds >> 1); //modified to truncate into two second intervals - jn

    return tmr;
}

下面是修改后的代码:我将小时、分钟和秒显式转换为 DWORD 类型。令人费解的是为什么原作者会转换 Month、DayOfMonth 而不是其他 uint8_t 类型。

DWORD get_fattime(void)
{
    DWORD tmr;

    /* Pack date and time into a DWORD variable */
    Calendar curTime = sdInterface->sdGetRTCTime();

    tmr = ((DWORD)(curTime.Year-1980)<<25)
            | ((DWORD)(curTime.Month) << 21)
            | ((DWORD)(curTime.DayOfMonth) << 16)
            | ((DWORD)(curTime.Hours) << 11)
            | ((DWORD)(curTime.Minutes) << 5)
            | ((DWORD)(curTime.Seconds) >> 1); //modified to truncate into two second intervals - jn

    return tmr;
}

代码似乎可以工作。希望有经验的程序员进行健全性检查。

我正在更新这篇文章以提供所需的信息:首先是结构日历 curTime。

//
//! \brief Used in the RTC_C_initCalendar() function as the CalendarTime
//! parameter.
//
//*****************************************************************************
typedef struct Calendar {
    //! Seconds of minute between 0-59
    uint8_t Seconds;
    //! Minutes of hour between 0-59
    uint8_t Minutes;
    //! Hour of day between 0-23
    uint8_t Hours;
    //! Day of week between 0-6
    uint8_t DayOfWeek;
    //! Day of month between 1-31
    uint8_t DayOfMonth;
    //! Month between 1-12
    uint8_t Month;
    //! Year between 0-4095
    uint16_t Year;
} Calendar;

下图显示了运行原始代码的 SD 卡的目录(没有对小时、分钟和时间 uint8_t 对象进行 DWORD 转换)。请注意其中两个文件缺少日期时间戳。这些目录也缺少日期时间戳。

enter image description here

下面的最后两张图显示了将 DWORD 应用于 uint9_t 对象的代码的结果。目录和文件现在都有日期时间戳。

Directories now have correct timestamps

And the files also have correct timestamps

从迄今为止收到的评论来看,我倾向于这是一个编译器错误。该代码是在早期版本的编译器上开发的。这是一个新的编译器 CCS v9。

最佳答案

[这并不是一个真正的答案,但对于评论来说太复杂了。]

请尝试这个程序:

#include <stdio.h>

int main()
{
    uint8_t b = 9;
    DWORD w1 = b << 6;
    DWORD w2 = (DWORD)b << 6;
    printf("%d %d\n", (int)w1, (int)w2);
}

该程序的预期输出是

576 576

右移 6 位相当于乘以 64,9 × 64 = 576,所以这是有道理的。

如果,另一方面,你得到输出

64 576

我相信这表明您的编译器中存在错误。如果您将 9 在 8 位字段内左移 6 位,就会得到 64,这意味着您会从左侧丢失一点。

这(几乎)是有道理的,这就是@jaz_n 发布的答案所要表达的意思。但是,您的编译器不应移动 8 位字段中剩余的任何内容。当你写的时候

x << 6

其中x是类型uint8_t,编译器应该做的第一件事是将x提升为全角整数类型, 然后将其左移 6 位,该字段的宽度与机器上的 int 类型一样宽(通常为 16 位或 32 位)。 p>

这解释了为什么不需要对 DWORD 进行三个“额外”转换。您必须添加它们的事实表明您的编译器可能有问题。如果您的编译器为我的测试生成了打印 64 576 的代码,则这是您的编译器错误的额外证据。

关于C Actor : Is this expression coded correctly?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57631810/

相关文章:

c - 我的 C 生成文件有什么问题?

c - 我混淆的按位运算

java - 将不同的对象存储在从同一抽象类扩展的容器中

c++ - 函数式转换被认为是有害的?

sql - 如何在 Firebird 中四舍五入一个数字?

C使用sha2哈希函数

c - 为什么霍夫曼树代码需要 unsigned char

将二进制转换为多个字符

javascript - Jquery 除法转换为 int 问题

java - 方法引用转换如何工作?