【问题标题】:Conversion from null-integer to pointer in comma list从空整数转换为逗号列表中的指针
【发布时间】:2015-11-10 18:37:27
【问题描述】:

我知道在我们的现代世界中,NULL 和 0 并不是使用指针操作的最佳实践,并且根据 cppreference:

指针转换 一个空指针常量(见 NULL),可以是 转换为任意指针类型,结果为空指针 该类型的值。这种转换(称为空指针转换) 允许作为单次转换转换为 cv 限定类型, 也就是说,它不被视为数字和限定符的组合 转化率。

但是为什么这个代码是不允许的,而 gcc 和 clang 给我一个错误?

A* foo()
{
    return (bar(), NULL);
}

错误:从 long int 到 A* 的无效转换

【问题讨论】:

  • 您的意思是在 gcc 中允许,而在 clang 中出错?
  • 请发布完整的代码。我们不知道Abar() 是什么,可能有一个重载的operator,,甚至可能有宏使问题进一步复杂化(事实上,NULL 是一个宏,所以如果没有#include,您将无法使用它。
  • 我怀疑编译器将 NULL 转换为与 bar 的返回类型相同的类型,因为它是逗号表达式的一部分。然后将其转换为 A 指针时遇到问题。

标签: c++ pointers null c++98


【解决方案1】:

这里的问题是

(bar(), NULL)

是使用comma operator的表达式。

在逗号表达式 E1, E2 中,表达式 E1 被求值,其结果被丢弃,其副作用在表达式 E2 开始求值之前完成(注意,用户定义的运算符,不能保证顺序)。

逗号表达式结果的类型、值和值类别正是第二个操作数 E2 的类型、值和值类别。如果 E2 是临时的,则表达式的结果就是那个临时的。如果 E2 是位域,则结果是位域。

所以(bar(), NULL) 的类型被确定为long int 因为这是NULL 的类型所以它试图将long int 的值NULL 转换为A*会失败。

如果我们将代码更改为

A* foo()
{
    return NULL;
}

这将编译为使用NULL 的值并且NULL 的值可以分配给一个指针。

【讨论】:

    【解决方案2】:

    答案已在您的问题中给出。

    一个空指针常量(见NULL),可以转换为任何 指针类型,结果是该类型的空指针值。

    NULL 是常数,bar(), 0 不是常数。

    只是比较:

    A* foo()
    {
        return 0;
    }
    

    A* foo()
    {
        int v = 0;
        return v;
    }
    

    A* foo()
    {
        const int v = 0;
        return v;
    }
    

    【讨论】:

    • 在最后一个代码中,sn-p v 是 const 但它不能编译
    • 它由 GCC C++98 编译(见问题标签),但它不能由 C++11 编译。
    • 这是有道理的。想象一下代码 int a = std::rand();常量 int c = a; A* f = c;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-03
    • 1970-01-01
    • 2021-02-13
    • 2020-11-30
    相关资源
    最近更新 更多