【问题标题】:Can the NULL macro actually be a nullptr?NULL 宏实际上可以是一个 nullptr 吗?
【发布时间】:2018-07-31 22:08:04
【问题描述】:

根据标准草案N4713(7.11/1):

空指针常量是一个整数文字 (5.13.2),其值为 0 或类型为 std::nullptr_t 的纯右值。

和 21.2.3/2:

NULL是一个实现定义的空指针常量。

遵循NULL 可以定义为nullptrcppreference 也有提到:

#define NULL 0
//since C++11
#define NULL nullptr

同时“加法运算符”子句说 (8.5.6/7):

如果将值0 与空指针值相加或减去,则结果为空指针值。如果两个空 减去指针值,结果比较等于转换为类型std::ptrdiff_t 的值0

因此下面的代码应该是有效的:

0 + nullptr; 
nullptr - nullptr; 

但由于 std::nullptr_tcode is invalid 缺少 +/- 运算符。

是否有什么我没有考虑到或者NULL 宏实际上不能定义为nullptr

【问题讨论】:

  • 是的,它可以。 [[[[[[[[[[
  • “有什么我没有考虑到的”,是的,你可以在字面量 0 上加 0。
  • 空指针value和空指针constant是两个截然不同的东西。
  • @Cheersandhth.-Alf 是,但不是“空指针值”。
  • @Cheersandhth.-Alf 当然是std::nullptr_t类型的值,它不是指针类型,所以没有理由称它为“空指针值”(它不是指针完全有价值)。无论如何,“加法运算符”子句列出了可能参与加法运算符的类型,而std::nullptr_t 不是其中之一,因此无论您是否调用std::nullptr“空指针值”,std::nullptr - std::nullptr 都是无效的。

标签: c++ null language-lawyer nullptr


【解决方案1】:

虽然nullptr 是一个空指针常量,但它不是一个空指针。后者是某个指针类型的值,std::nullptr_t 不是。

参考:

空指针常量是一个整数文字 (5.13.2),其值为零或类型为 std::nullptr_t 的纯右值。 空指针常量可以转换为指针类型;结果是该类型的空指针值,并且是 可与对象指针或函数指针类型的所有其他值区分开来。这种转换称为 空指针转换。 [...]

N4659 中的 7.11/1,强调我的

所以NULL确实可以是nullptr而不提供算术运算符。

【讨论】:

  • @Cheersandhth.-Alf - 不,他应该投赞成票,因为标准文本将 空指针值 视为一个术语,而不仅仅是 值我>。而且,如果您想挖掘过去的遭遇,请不要去指责他人的私人化。
  • @Cheersandhth.-Alf 抱歉,我没看到 "nullptr 本身不是指针值也不是指针。因此算术运算不适用于nullptr"如果“它不是空指针值”是错误的,则i>是正确的。
  • @Cheersandhth.-Alf C++17 7.11/1 "一个 空指针常量 是一个整数字面量 (5.13.2),其值为 0 或类型为 @ 的纯右值987654328@。空指针常量可以转换为指针类型;结果是该类型的空指针值,并且可以与对象指针或函数指针类型的所有其他值区分开来。这样的转换被称为空指针转换。”这似乎很清楚地表明nullptr(或std::nullptr_t 类型的任何其他纯右值)不是“空指针值。”
  • @Cheersandhth.-Alf 是否是一个值是不可能的,但它在哪里说它是一个空指针值?
  • 我需要新的眼睛。很抱歉造成混乱!
【解决方案2】:

nullptr 是一个空指针字面量,虽然将nullptr 转换为指针类型的结果是空指针值,但nullptr 本身不是指针类型,而是std::nullptr_t 类型。如果您确实将 nullptr 转换为指针类型,则该算法有效:

0 + (int*)nullptr; 
(int*)nullptr - (int*)nullptr;

NULL 宏真的可以是 nullptr 吗?

是的,因为nullptr 是一个空指针文字。

请注意,在 C++11 之前,C++ 中的所有空指针文字恰好也是整数文字,所以这个糟糕的代码:char c = NULL; 曾经在实践中工作。如果 NULL 定义为 nullptr,则该代码不再有效。

【讨论】:

    【解决方案3】:

    另外,两个操作数都应具有算术或无作用域枚举类型,或者一个操作数应是指向完全定义的对象类型的指针,而另一个应具有整数或无作用域枚举类型。

    对于减法,应满足以下条件之一:
    (2.1) 两个操作数都有算术或无范围枚举类型;或
    (2.2) 两个操作数都是指向同一完全定义对象类型的 cv 限定或 cv 非限定版本的指针;或
    (2.3) 左操作数是指向完全定义对象类型的指针,右操作数是整数或非作用域枚举类型。

    std::nullptr_t 不是这些,因此std::nullptr 不能参与加法运算。

    请注意,并非所有指针值都可以参与。例如,函数指针值和 void 指针值不能,即使它们都可以是空指针值。

    【讨论】:

      【解决方案4】:

      关键字nullptr 表示指针字面量。它是std::nullptr_t 类型的prvalue。存在从nullptr 到任何指针类型的空指针值和任何指向成员类型的指针的隐式转换。 nullptr 本身既不是指针值也不是指针。因此算术运算不适用于nullptr

      【讨论】:

      • 所以 8.5.6/7 不适用于nullptr,因为它不是空指针值? (在阅读了 Baums 的答案后删除了此评论,并在阅读了该答案下面的讨论后重新发布;)
      • 如果nullptrstd::nullptr_t 类型,而不是指针类型,它怎么是指针字面量?您可能需要考虑重新措辞更准确。
      • @user463035818 是的,你是对的。 prvalue(“纯”右值)是不是xvalue 的右值。 [示例:调用返回类型不是引用的函数的结果是prvalue] - 从这里复制stackoverflow.com/questions/3601602/…
      • @StoryTeller NULL 是实现定义的空指针常量。 nullptr_t 是空指针字面量nullptr 的类型,如char 是字符字面量'a' 的类型,或者const char const * 是字符串字面量"abc" 的类型。
      • 我认为你没有达到我的目标。字面量是类型化 值。由于nullptr_t 不是指针类型,nullptr 不能是指针文字。
      猜你喜欢
      • 2020-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多