c++ - c++中值0的特殊状态是什么?

标签 c++ literals null-pointer

这纯粹是一个哲学问题。我认为没有合理的上下文可以证明结果是有用的(给定 nullptr)。

据此 - https://en.cppreference.com/w/cpp/language/integer_literal ,整型文字的类型为 int , long int , long long int , unsigned int , unsigned long intunsigned long long int ,如果文字的值不符合上述任何一项,则可能存在特定于实现的异常(exception)。
这些类型都不能转换为 void * , 除非文字的值为 0。

不同的编译器对此有不同的处理方式。
例如,考虑以下转换:

void g(void * p){}

void f(){
    int i = 0;
    void * p;
    // p = i; // Fails. Also for other integral types.

    p = 0; // Works. Also for 00, 0x0 and 0b0. Also when adding `u` and `l` suffixes.
    g(0); // Also works.    
    // g(1); // Fails.  

    // Amazingly, even this seems to work with gcc, icc and msvc, but not with clang:
    void * x = static_cast<int>(0);
    // These works for icc and msvc, but fails with gcc and clang
    p = static_cast<int>(0);
    g(static_cast<int>(0));
}

使编译器能够执行这些操作的“幕后”发生了什么int -> void *转换?

编辑:
具体来说,问题是标准对此有何规定?

最佳答案

The question is, why is this permitted according to the standard



因为需要有一种方式来表达空指针。 C 语言的设计者选择 0 为空。 C++ 的设计者选择与 C 兼容,因此 0 是空指针常量。

稍后在 C++11 中,nullptr被作为新关键字引入。不能替换整型空指针常量,因为那样会破坏向后兼容性,因此这些不同的空指针表示方式共存。如果您不需要支持 C++11 之前的系统,则没有理由使用 0 作为空指针。

and specifically what is permitted



标准说(最新草案):

[conv.ptr] A null pointer constant is an integer literal ([lex.icon]) with value zero or a prvalue of type std​::​nullptr_­t. A null pointer constant can be converted to a pointer type; the result is the null pointer value of that type ([basic.compound]) and is distinguishable from every other value of object pointer or function pointer type. Such a conversion is called a null pointer conversion. Two null pointer values of the same type shall compare equal. The conversion of a null pointer constant to a pointer to cv-qualified type is a single conversion, and not the sequence of a pointer conversion followed by a qualification conversion ([conv.qual]). A null pointer constant of integral type can be converted to a prvalue of type std​::​nullptr_­t. [ Note: The resulting prvalue is not a null pointer value. — end note ]



What happens "under the hood" that enables compilers to perform these int->void * conversions?



编译器解析源。语法说 0 是文字。编译器将 is 视为文字 0,因此可以按照标准将其转换为任何指针类型。
// Amazingly, even this seems to work with gcc, icc and msvc, but not with clang:
void * x = static_cast<int>(0);

这是自 C++11 以来格式错误的。当一个格式错误的程序编译时,通常是因为
  • 它是语言扩展或
  • 这是一个编译器错误或
  • 它在旧版本的语言中格式良好,编译器针对

  • 在这种情况下,它可能是一种语言扩展。
    // These works for icc and msvc, but fails with gcc and clang
    p = static_cast<int>(0);
    g(static_cast<int>(0));
    

    从 C++11 开始,这些也是格式错误的。我对 icc 和 msvc 了解不够,无法告诉您这些情况是否是故意的。我建议检查他们的文档。

    关于c++ - c++中值0的特殊状态是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62025176/

    相关文章:

    c++ - ISO C++ 禁止声明没有类型的 ‘Expresion’

    java - Java中的类文字是什么?

    c - 'fopen' 返回 NULL 文件指针,即使文件是使用 C 创建的

    c - NULL 和 0 在 C 中是否完全等价?

    python - 逻辑索引 - C++ 中的 numpy.where

    c++ - 多维数组作为类成员分配在堆上

    java - java关键字和字面量的区别

    c++ - 为什么 std::string 不采用空指针?

    c++ - 使用 map 查找具有给定总和(带负数)的子数组

    javascript - 如何将动态变量传递给 JS 中的函数?