【问题标题】:Is max(a,b) defined in stdlib.h or not?max(a,b) 是否在 stdlib.h 中定义?
【发布时间】:2011-05-13 03:37:08
【问题描述】:

我正在使用两台计算机,每台计算机都有不同版本的 Visual Studio。在 Visual Studio 2008 计算机上,我的代码可以编译。在可视化 2010 计算机上,我的代码无法编译,因为我使用的是宏 max(a,b),据我所知,它在 stdlib.h 中定义。我不能只定义max(a,b),因为它会在visual 2008 计算机上重新定义。但是,如果我不定义 max(a,b),我的代码将无法在 Visual 2010 计算机上编译。

有什么办法吗?

【问题讨论】:

  • 除了接受的答案中讨论的可移植性问题之外,我很好奇为什么您在使用 max() 宏从 VS2008 移动到 VS2010 时遇到问题。 max() 在 VS2010 的 stdlib.h 中定义与在 VS2008 中的定义方式相同(有一些选项会关闭定义,但在两个编译器中它们是相同的)。换句话说,不仅仅是从 VS2008 迁移到 VS2010(在 stdlib.h 中定义的 max() 不符合标准)给您造成了这个问题。
  • 在我的 Visual C 中,stdlib.h 定义了 __min 和 __max。
  • 在 Visual Studio 2015 中,最小值和最大值仍在 stdlib.h 中定义...

标签: c visual-studio macros max std


【解决方案1】:

你可以使用条件编译:

#ifndef max
  #define max(a,b) ...
#endif

【讨论】:

  • #undef max 会好很多。如果 MSVC 被破坏到在标准头文件中定义 max 宏,你真的可以相信他们能正确定义它吗? :-)
【解决方案2】:

使用#ifndef 保护它。

#ifndef max
    #define max(a,b) ((a) > (b) ? (a) : (b))
#endif

请记住,上面的版本不如内联函数安全,例如max(a++,b--) 会导致意想不到的结果。

【讨论】:

  • 您的宏给出了两个数字中的最小值。应该是(a) > (b)
  • 对过去 5 年没有人注意到这一点感到惊讶。固定!
【解决方案3】:

任何在其标准头文件中定义名为 max 的宏的 C 库都超出了想象。幸运的是,如果您需要支持此类平台,一个简单的解决方法是 #undef max(以及它定义的任何其他有问题的宏)在包含系统标头之后和您自己的任何标头/代码之前。

请注意,其他人都说要将您的定义包含在 #ifndef max ... #endif 中。这不是好主意。在系统标头中定义max 表明实现者不称职,并且某些版本的环境可能具有不正确 宏(例如,没有正确保护带括号的参数的宏,但我什至见过max 宏在我的生命中至少一次错误地执行min 而不是max!)。只需使用#undef 并确保安全。

至于为什么stdlib.h 定义max 如此糟糕,C 标准非常具体地规定了哪些名称是为应用程序保留的,哪些名称是为标准函数和/或实现内部使用保留的。这有很好的理由。在系统头文件中定义可能与应用程序中使用的变量/函数名称冲突的宏名称是危险的。在最好的情况下,它会导致具有明显原因的编译时错误,但在其他情况下,它可能会导致非常奇怪的行为,难以调试。在任何情况下,编写可移植代码都变得非常困难,因为您永远不知道库已经采用了哪些名称。

【讨论】:

  • 删除了我的答案:目前你的答案是最合适的。
  • @R.. 谢谢,但你能解释一下为什么定义 max 的 C 库超出想象吗?
  • 您关于为什么<stdlib.h> 不应定义max 的问题在一定程度上是有效的。如果用户明确请求实现提供的额外定义(例如,通过定义__EXTENSIONS__(非官方)或_POSIX_C_SOURCE(官方)),则允许<stdlib.h> 提供额外定义。在许多平台上,默认情况下可以启用扩展,并且只有通过请求“标准符合模式”才能使其不可用。
  • @Jonathan:不过,定义意外宏对程序员来说比定义意外函数更难,这也是事实。编译器错误(如果有的话)不太可能产生很大的意义。
  • 不过,这里的例子 (max) 非常极端。我会在将#define i _Complex_I 放在标准头文件中的情况下仅将其放在一个或两个级别的坏处。另请注意,在这种情况下,禁用扩展的唯一方法是在为应用程序 (#define NOMINMAX) 保留的命名空间中使用另一个宏,这排除了实现符合要求的任何希望。
【解决方案4】:

在 Visual C++ 中,如果在包含标准头文件之前#define NOMINMAX,您将不会获得宏 max 或 min。

【讨论】:

  • 这是另一个错误。如果他们改为使用_NOMINMAX,它将是符合要求的,但NOMINMAX 是为应用程序保留的,标准库头文件将其用于自己的目的是不符合要求的。
【解决方案5】:

所以回答你的主要问题:

在 stdlib.h 中是否定义了 max(a,b)?

不,不是,它在 windef.h 中的第 187 行附近定义:

#ifndef NOMINMAX

#ifndef max
#define max(a,b)            (((a) > (b)) ? (a) : (b))
#endif

#ifndef min
#define min(a,b)            (((a) < (b)) ? (a) : (b))
#endif

#endif  /* NOMINMAX */

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-23
    • 1970-01-01
    • 2013-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-19
    相关资源
    最近更新 更多