负时间转换给出随机值

4 c time initialization integer-overflow undefined-behavior

我正在尝试计算 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;
}
Run Code Online (Sandbox Code Playgroud)

alk*_*alk 5

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

struct tm ts;
Run Code Online (Sandbox Code Playgroud)

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

struct tm ts = {0};
Run Code Online (Sandbox Code Playgroud)

至少。


此外假设

unsigned int jahr_tod_von_1900;
int jahr_tod_negative;
Run Code Online (Sandbox Code Playgroud)

这个说法

 jahr_tod_von_1900 = 1900 - jahr_tod;
Run Code Online (Sandbox Code Playgroud)

导致 的signed整数环绕jahr_tod > 1900。后者的“溢出”也会导致未定义的行为。要这样做

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

jahr_tod_von_1900 = 1900U - (unsigned int) jahr_tod;
Run Code Online (Sandbox Code Playgroud)