【问题标题】:Negative time conversion gives random values负时间转换给出随机值
【发布时间】:2016-04-23 08:42:20
【问题描述】:

我正在尝试计算 C 中两个时间点之间的差异,因为这些点在 1900 年之前,我需要使用负值。

虽然转换应该将变量jahr_tod_negative 写入ts.tm_year,但几乎每次我运行程序时,它都会给我一个完全不同的日期,甚至日期和月份都混淆了。年份是唯一需要为负的值。我怎样才能防止这种情况发生?

#include <stdio.h>
#include <time.h>

int main ()
{

    time_t t;
    struct tm ts;
    char str[90];

    int tag_tod;
    int monat_tod;
    int jahr_tod;
    unsigned int jahr_tod_von_1900;
    int jahr_tod_negative;


    printf("Tag eingeben: ");
    scanf("%d", &tag_tod);
    printf("\nMonat eingeben: ");
    scanf("%d", &monat_tod);
    printf("\nJahr eingeben: ");
    scanf("%d", &jahr_tod);
    jahr_tod_von_1900 = 1900 - jahr_tod;
    jahr_tod_negative = -jahr_tod_von_1900;
    printf("jahr_tod_negative: %d\n", jahr_tod_negative);


    //ts.tm_sec     = 0;
    //ts.tm_min     = 0;
    //ts.tm_hour  = 0;
    ts.tm_mday  = tag_tod;
    ts.tm_mon   = monat_tod;
    ts.tm_year  = jahr_tod_negative;     /* Jahr - 1900 */
    //ts.tm_wday  = 0;
    //ts.tm_yday  = 0;
    //ts.tm_isdst = 0;

    t = mktime(&ts);
    //printf("%s", asctime(&ts));
    printf("ts.tm_year: %d\n", ts.tm_year);
    strftime(str, 90, "%d. %B %Y", &ts);
    printf("Eingegebenes Datum: %s\n", str);

    return 0;
}

【问题讨论】:

  • 谁告诉你这应该有效?我完全不确定,但我担心它不能。
  • @jdarthenay 大约 4/10 次输出正确的值,另外 6 次似乎是随机的。
  • 这很有趣。很高兴有机会 UPvote 改变问题:)
  • 你能给出你正在使用的输入吗?如果您正在构建 32 位或 64 位程序,也很精确。
  • @jdarthenay 尝试输入:例如1456(有效),1568(随机数),每一个大于 1900 的数都输出正确的值。顺便说一句,它是 64 位。

标签: c time initialization undefined-behavior integer-overflow


【解决方案1】:

对于初学者:您要正确初始化

struct tm ts;

在使用它之前。否则代码很可能会遇到未定义的行为,所以任何事情都可能发生。

struct tm ts = {0};

至少。


进一步假设

unsigned int jahr_tod_von_1900;
int jahr_tod_negative;

这句话

 jahr_tod_von_1900 = 1900 - jahr_tod;

导致signed 整数环绕jahr_tod &gt; 1900。后一种“溢出”也会导致未定义的行为不要这样做。

无论如何,当您分配给unsigned 时,要解决此问题,请确保您执行“无符号”减法,例如这样:

jahr_tod_von_1900 = 1900U - (unsigned int) jahr_tod;

【讨论】:

    【解决方案2】:

    问题(可能还有其他问题)在于

    jahr_tod_von_1900 = 1900 - jahr_tod;

    您在哪里声明:

    unsigned int jahr_tod_von_1900;

    如果jahr_tod 实际上大于1900,会发生什么?您将负值隐式转换为无符号整数,因此通常会得到一个非常大的值。

    如果我扔掉所有 jahr_tod_negative 的东西,只使用(一次!)

    ts.tm_year = jahr_tod - 1900;

    我总是得到正确的答案。

    【讨论】:

    • 大于 1900 的值给出正确的输出,因为正值被添加到 1900。
    • 猜测答案大多无济于事。这样往往会使答案成为低质量的答案... :-( 如果不确定,最好发表评论。
    • @alk 我尝试了我的解决方案:即使没有初始化它也可以在 OS X 上运行。所以溢出是一个问题
    • 我并不反对你写的关于“溢出”的内容,而是你写它的方式(-->“我认为”)。如果不确定不回答。简单! ;-)
    • @alk,好的,我先写了我的假设,然后按原样编译代码,并尝试重写,然后给出了正确的结果。的确,他不投,糟糕的术语......
    猜你喜欢
    • 1970-01-01
    • 2016-11-14
    • 2018-05-08
    • 2012-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-19
    相关资源
    最近更新 更多