【问题标题】:Error code with implementation of time_t in C++在 C++ 中实现 time_t 的错误代码
【发布时间】:2015-05-18 01:55:51
【问题描述】:
time_t rawtime;
struct tm * timeinfo;

time(&rawtime);
timeinfo = localtime(&rawtime);

heure_= timeinfo->tm_hour;
minute_ = timeinfo->tm_min;
seconde_ = timeinfo->tm_sec;
jourMois_ = timeinfo->tm_mday;
jourSemaine_ = timeinfo->tm_wday;
mois_ = timeinfo->tm_mon;
annee_ = timeinfo->tm_year;

这是我对查找时间、日期、....等函数的实现。

我不知道为什么,但我得到了错误:

1>c:\users\sebastien\blabla: 警告 C4244: 'argument' : 从 'time_t' 转换为 'unsigned int',可能丢失数据

1> DateHeure.cpp

1>c:\users\sebastien\blabla-> 错误 C4996: 'localtime': 此函数或变量可能不安全。考虑改用 localtime_s。要禁用弃用,请使用 _CRT_SECURE_NO_WARNINGS。有关详细信息,请参阅在线帮助。

1> c:\program files (x86)\microsoft visual studio

12.0\vc\include\time.inl(112) : 参见“localtime”的声明

我尝试将 localtime 更改为 localtime_s,但我收到一些关于与“tm”类型参数的兼容性的错误消息。

我也尝试过(包括或纠正)__CRT_SECURE_NO_WARNINGS 但没有成功 -> 我不知道,但只包括这一行似乎很奇怪(在属性>c++>预处理器>未定义的预处理器定义中)而不添加任何其他内容。

承认我对 Visual Studio 不是很熟悉,所以我不确定所有这些属性设置和调整。

但如果有人能帮我解决这个问题,我将不胜感激,我认为这是我唯一的错误,我会在确定之后进行调试。

请提供一些有关原因的信息...我想了解一下。

【问题讨论】:

  • 是 C 还是 C++?添加语言标签。
  • @余浩,你能告诉我为什么你把所有的 i 都改成了大写,尽管它们不是都开始一个句子吗? (英语不是我的母语,对错误深表歉意)但是人们在这里做的事情吗? (有什么共鸣)
  • I 总是用英文大写字母书写。

标签: c++ time


【解决方案1】:

C4996 不应该是错误,我想您调整了编译选项以使其成为错误。 (或project wizard did

无论如何,不​​使用静态本地缓冲区的替代函数更好,而且它们也是可移植的(除了名称之外,在 Win32 上是 localtime_s 在 Linux 上是 localtime_r,宏可以修复),所以真的没有理由不使用它们。

没有静态本地缓冲区的版本希望您提供缓冲区,这很容易:

time_t rawtime;
struct tm timeinfo;  // no longer a pointer

time(&rawtime);

// on platforms with POSIX localtime_r but no localtime_s, add this macro
// #define localtime_s(x, y) localtime_r(y, x)
localtime_s(&timeinfo, &rawtime); // fills in your structure,
                                  // instead of returning a pointer to a static one

heure_= timeinfo.tm_hour;  // no longer using a pointer
minute_ = timeinfo.tm_min;
seconde_ = timeinfo.tm_sec;
jourMois_ = timeinfo.tm_mday;
jourSemaine_ = timeinfo.tm_wday;
mois_ = timeinfo.tm_mon;
annee_ = timeinfo.tm_year;

【讨论】:

  • 我会看看它们之间的区别,我只是没有发现任何说我必须使用两个参数而不是一个参数(使用 localtime_s)...我需要更多地查看您的代码,但是,谢谢先生,真的很有帮助。
  • 如果对如何调用函数有疑问,可以随时参考documentation。找到它通常就像将光标放在函数名称上并按 F1 一样简单。
【解决方案2】:

localtime 函数可能是不安全的,因为它返回的指针指向一个用于自身和其他调用的结构。这意味着,如果您调用一个更改该内部结构的函数,所有指向它的指针都会反映新数据。

如果您知道在您完成数据之前不会修改数据,那么您仍然可以安全地使用它。在这种情况下,您可以执行以下操作:

#define _CRT_SECURE_NO_WARNINGS 1
#include <ctime>
#include <iostream>

int main()
{
    time_t rawtime = time(nullptr);
    tm* timeinfo = localtime(&rawtime);

    std::cout << asctime(timeinfo) << "\n";
    return 0;
}

如果您希望使用更安全的 localtime_s 来填充您传入的不会意外更改的结构,那么您可以像这样使用它:

#include <ctime>
#include <iostream>

int main()
{
    time_t rawtime = time(nullptr);
    tm timeinfo;
    errno_t error = localtime_s(&timeinfo, &rawtime);
    if(error != 0)
    {
        std::cerr << "localtime_s failed.\n";
        return -1;
    }

    std::cout << asctime(&timeinfo) << "\n";
    return 0;
}

请记住,localtime_s 可能并非在所有平台上都可用,因此它可能不太便携。

【讨论】:

  • 其他重要的平台有localtime_r... 因为静态本地缓冲区确实是个坏主意。除了名称之外,唯一的区别是localtime_r 切换了两个参数......并且一个宏可以轻松解决这个问题。
  • 没错,不过如果他们支持 C11,他们也可能有 localtime_s
  • 嗯,两者兼而有之。它被命名为localtime_s,但它返回一个类似于posix 版本的指针,而不是Microsoft 版本的错误代码。有点乱。
  • localtime_s() 的 C11 标准变体在 ISO/IEC 9899:2011 附录 K.3.8.2.4 中定义为 struct tm *localtime_s(const time_t * restrict timer, struct tm * restrict result);,而 MSDN localtime_s() 定义为 errno_t localtime_s( struct tm* _tm, const time_t *time );。另请参阅 Do you use the TR-24731 'safe' functions? 我以前不知道这组差异。
  • @BenVoigt:C 标准 localtime_s() 名称与 POSIX localtime_r() 具有相同的签名。 *_s() 函数的微软实现是,AFAICT,一成不变(通过发布)并提交给 C 标准委员会,委员会做出了明智的改变——但损害已经造成,因为微软已经发布了他们的变体。这是一个令人难以置信的混乱,确实非常不幸。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多