char* p=NULL, cout<<p;给出例外
char* p=NULL, cout<<p; gives exception
我最近在面试中被问到这个问题:
char* p = NULL;
cout << p << endl;
++p;
cout << p << endl;
我给出的答案是第一个 cout 将打印 00000,接下来将打印 00001。
但是当我在 visual studio 中检查它时,它给出了一个异常:
StringFunctions.exe 中 0x009159F1 的第一次机会异常:0xC0000005:访问冲突读取位置 0x00000000。
StringFunctions.exe 中 0x009159F1 处的未处理异常:0xC0000005:访问冲突读取位置 0x00000000。
但是对于 int、float 等它可以正常工作。
有人可以解释一下吗?
感谢您的帮助!
当然,在最简单的解释中,cout 尝试引用指针并打印字符串,因为您传递了一个 char 指针
理解这一点的最好方法是下面的一段代码。
char *s = "hello";
cout << s+2 << endl; // Or &s[2]
它会输出 "llo",因为第一个预感会是 "print address of first l"
输出流知道,当您传递 char*
时,您想要打印一个字符串。您传递了一个未初始化的指针。它试图将其作为 C 字符串读取……而且,这会调用未定义的行为。
如果你想先打印一个转换为 void*
的地址,即 static_cast<void*>(p)
.
顺便说一句,NULL
不能保证评估为 0
(在所有 0
位意义上)。但是可以保证将 与 等同地与 0
进行比较。不是一回事。此外,您的增量也会调用 UB。
std::cout::operator<<
的 char*
重载需要一个以 null 结尾的 C 字符串。这就是它试图访问指针的原因。
要绕过此行为,请先将指针转换为 void*
。
我最近在面试中被问到这个问题:
char* p = NULL;
cout << p << endl;
++p;
cout << p << endl;
我给出的答案是第一个 cout 将打印 00000,接下来将打印 00001。 但是当我在 visual studio 中检查它时,它给出了一个异常: StringFunctions.exe 中 0x009159F1 的第一次机会异常:0xC0000005:访问冲突读取位置 0x00000000。 StringFunctions.exe 中 0x009159F1 处的未处理异常:0xC0000005:访问冲突读取位置 0x00000000。
但是对于 int、float 等它可以正常工作。 有人可以解释一下吗? 感谢您的帮助!
当然,在最简单的解释中,cout 尝试引用指针并打印字符串,因为您传递了一个 char 指针
理解这一点的最好方法是下面的一段代码。
char *s = "hello";
cout << s+2 << endl; // Or &s[2]
它会输出 "llo",因为第一个预感会是 "print address of first l"
输出流知道,当您传递 char*
时,您想要打印一个字符串。您传递了一个未初始化的指针。它试图将其作为 C 字符串读取……而且,这会调用未定义的行为。
如果你想先打印一个转换为 void*
的地址,即 static_cast<void*>(p)
.
顺便说一句,NULL
不能保证评估为 0
(在所有 0
位意义上)。但是可以保证将 与 等同地与 0
进行比较。不是一回事。此外,您的增量也会调用 UB。
std::cout::operator<<
的 char*
重载需要一个以 null 结尾的 C 字符串。这就是它试图访问指针的原因。
要绕过此行为,请先将指针转换为 void*
。