Q. 有点错误所以请检查正文 C float *q=NULL; printf("%f",q) ;输出是 0.000000 但在 C++ 中 float *q=nullptr; cout<<q;给输出 0?

问题描述

[我的问题有点奇怪,但现在改变它是不对的,因为它得到了很好的解释,但我正在用[更新].......[更新结束]标签编辑它以避免使即将访问我的帖子的访问者感到困惑]

C

#include<stdio.h>
int main()
{
    float *q=NULL;
    
    printf("%f\n",q);
}

输出

0.000000
  • 在 C 中输出为 0.000000
  • 所以这里 q 是浮点型空指针还是仍然是 (void *) 型空指针?
  • 我觉得它是 (void *) 类型。
  • 因此格式不匹配(%f)和参数(void*)调用未定义 行为并导致此类错误类型输出

[更新] 但是你会填写我自己的问题的答案,我问的这么愚蠢的问题

基本上我很困惑,我觉得我必须打印一些浮点类型或空类型,但重点是我正在打印地址,所以使用 %f 来打印地址是愚蠢的。

显然 q 是浮点型指针,只是我觉得完全错误

通常我们使用 %u 来打印任何类型变量(int,char,float)的地址,但对于指针我们应该使用 %p

[更新结束]

C++

#include<iostream>
int main()
{
    float *q=nullptr;
    std::cout<<q;
}

输出

0
  • 在 C++ 中给出输出 0
  • 我认为这很好,因为它给出了第一个内存块的地址作为指向 一无所有
  • 如果 q 是 nullptr_t 类型,那么 C++11 应该给出 ambugity 错误 表示这里 q 是浮点型 nullptr。

[更新]

C 和 C++ 标准都指定空指针常量比较等于零 - 他们没有说明该地址处的内容

显然 q 只是浮点型 nullptr

[更新结束]

所以,如果我的两个假设都是正确的,那么为什么在 C++ nullptr 中将其类型从 nullptr_t 更改为浮点类型,但在 C 中 NULL 并没有将其类型从 (void ) 更改为 (float) ?

[更新]

我在第一个 C 示例中第一个假设 q 是 (void*) 类型已经是错误的 和第二个假设,在第二个例子。 C++的q为nullptr_t也是错误的。

这里总结一下

我试图比较这发生在 C 中和发生在 C++ 中,我觉得这些事情是相互矛盾的

但实际上在 C 中我使用 %f 来打印第一个错误的指针地址。在 C++ 代码中,我认为一切都很好,除了一件事是假设空指针指向第一个内存块是错误的,因为它没有在 c 标准中指定它只是说 nullptr 常量在评估时与 0 比较。

问题太多了,所以这不是正确的问题

[更新结束]

解决方法

printf("%f\n",q);

格式说明符 %f 要求传递的对象的类型为 double 类型(float 参数将被隐式转换,因此也可以)。您传递了错误类型的 float*。将错误类型的参数传递给 printf 会导致未定义的行为。

printf("%p",q);

这个有点微妙,但是 %p 说明符要求参数的类型为 void*float* 仍然是错误的类型,因此行为仍未定义。

您应该更加小心地使用正确的格式说明符和参数类型。 C 格式的 I/O API 非常无情。


在 C++ 中给出输出 0

请注意,输出是 0 还是其他取决于系统使用什么值来表示空指针。

为什么在 C++ nullptr 中将其类型从 nullptr_t 更改为浮点类型

nullptr 在您的示例中从未“将其类型更改为浮点类型”。在 float *q=nullptr 中,隐式转换为类型 float*

但在 C 中 NULL 并没有将它的类型从 (void ) 更改为 (float) ?

NULL 宏的类型不是 C 中的 void。它可以是整数常量 0,或者这样的常量转换为 void*。这两者都可以隐式转换为任何指针类型。这就是 float *q=NULL 中发生的事情。

因此,在两种语言中,您都将 null 隐式转换为指针类型。


无论哪些类型可以隐式转换为哪些类型,可变参数都不会隐式转换为格式字符串所需的类型,因为编译器不知道这些类型1 2

1 有我提到的从 float 到 double 的转换,但这些不依赖于格式说明符。

2 如果格式字符串是常量,一些编译器确实有助于诊断您的错误,但他们不需要这样做。

,

指针没有改变类型。在 cout 版本中,您让系统自然打印指针值。在 printf 版本中,您强制使用 %f。将格式字符串更改为 %ld,您将得到不同的结果。

printf 对您作为参数传递的内容一无所知。它相信程序员知道他在做什么。

---在此处编辑以回答更多问题---

您说得对,%lu 可能比 %ld 更好。我想您可能有一个设置了最高有效位的地址(这意味着 %ld 会认为它是负数)。

是:

float * q = nullptr;

表示 q 全为零。

Cout 知道正在打印什么并且(通常)做正确的事情。除非您非常特别地控制它,否则很少使用格式说明符(例如打印浮点数和双精度数时使用的位数)。我用它来设置 bool 的默认输出以打印 truefalse 而不是 10。但一般来说,使用 cout 时您可以获得合理的值,而无需任何额外的工作或认为必要。