C++程序员大挑战之二-令人疑惑的NULL指针!该如何解决
C++程序员大挑战之二----令人疑惑的NULL指针!
请看下面的程序
class foo
{
public:
foo() { m_nVar1 = 100;};
~foo(){};
void Display()
{
printf( " m_nVar2 is %d ", m_nVar2 );
}
int m_nVar1;
static int m_nVar2;
};
int foo::m_nVar2 = 500;
int main(int argc, char* argv[])
{
foo *p = NULL;
p-> Display();
_getch();
return 0;
}
请问哪种说法是正确的:
A. 程序编译错误。
B. 程序编译正确,但是运行时发生异常
C. 程序编译正确,运行时有时正常,有时发生异常。
D. 程序编译正确,运行时正常
你的选择是哪一个?
=========================================================
------解决方案--------------------
D. 程序编译正确,运行时正常
------解决方案--------------------
D
------解决方案--------------------
A, 没有必要的头文件
------解决方案--------------------
D
------解决方案--------------------
呵呵,楼上的真幽默。
其实关于这个问题我以前也说过不少。
p-> Display();
使得Display()方法中的this参量指向p,这里由于p指向空,所以,this也指空。
但是display()中并没有访问对象p的成员属性,只是访问了类属性——static int m_nVar2
它不在*p所处的存储空间中,而是在全局静态区域。所以这里没有访问空地址的内容,故程序运行时正常。
而如果在Display()方法中访问了m_nVar1,编译连接全通过,发生运行时异常(存储空间受保护情况下)。
------解决方案--------------------
不得不说,楼上的分析得完全正确。
不过我还是实际验证了一下。
如果仅仅使用搂主的代码,在VC6中的确编译不过。
Deleting intermediate files and output files for project 'TC2 - Win32 Debug '.
--------------------Configuration: TC2 - Win32 Debug--------------------
Compiling...
StdAfx.cpp
Compiling...
TC2.cpp
tc2.cpp(13) : error C2065: 'printf ' : undeclared identifier
tc2.cpp(25) : error C2065: 'NULL ' : undeclared identifier
tc2.cpp(25) : error C2440: 'initializing ' : cannot convert from 'int ' to 'class foo * '
Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
执行 cl.exe 时出错.
TC2.exe - 1 error(s), 0 warning(s)
加上#include <stdio.h> 就可以编译通过了。
当然,可能这个不是楼主的本意。
------解决方案--------------------
俺选D
------解决方案--------------------
1. 我测试了一下. 在 xp + vc-7_1 的环境下. 加上 #include <iostream> 后, 正常编译连接, 正常运行.
2. 但是我还是选 B. 我的理由是, Display 不是一个静态函数. 应该需要一个对象的实例的呀.
3. 我能想象的是, Display 方法被隐式的当作了 implicitly static member. 这点让我很迷惑. 我的记忆中, 只有 4 个方法可以作为隐式的静态成员方法. 分别是
T::operator new
T::operator delete
T::operator new[]
T::operator delete[]
4. 另外, NULL 不是 C++ 标准的东西, 它是编译器厂商的实现方案. 目前的标准采用的是 0. 如下:
foo *p = 0; // 这样比较标准
C++0x 似乎有意要将引入 nullptr 作为关键字, 专门针对指针. 不过那是后话了.
5. mark一下. lz 的题目出的挺有意思. 坚持下去哦. 希望能把 C++ 的边边角角都扫扫干净.
------解决方案--------------------
zenny_chen(ACE Intercessor) 说得很不错
偶补充一个 :)
void Display()
{
if (this)
printf( " m_nVar1 is %d ", m_nVar1 );
}
这样,你或许可以看出是什么回事情了:)
这个函数访问了 m_nVar1 ,即使是 NULL
对象也不会出错
------解决方案--------------------
请看下面的程序
class foo
{
public:
foo() { m_nVar1 = 100;};
~foo(){};
void Display()
{
printf( " m_nVar2 is %d ", m_nVar2 );
}
int m_nVar1;
static int m_nVar2;
};
int foo::m_nVar2 = 500;
int main(int argc, char* argv[])
{
foo *p = NULL;
p-> Display();
_getch();
return 0;
}
请问哪种说法是正确的:
A. 程序编译错误。
B. 程序编译正确,但是运行时发生异常
C. 程序编译正确,运行时有时正常,有时发生异常。
D. 程序编译正确,运行时正常
你的选择是哪一个?
=========================================================
------解决方案--------------------
D. 程序编译正确,运行时正常
------解决方案--------------------
D
------解决方案--------------------
A, 没有必要的头文件
------解决方案--------------------
D
------解决方案--------------------
呵呵,楼上的真幽默。
其实关于这个问题我以前也说过不少。
p-> Display();
使得Display()方法中的this参量指向p,这里由于p指向空,所以,this也指空。
但是display()中并没有访问对象p的成员属性,只是访问了类属性——static int m_nVar2
它不在*p所处的存储空间中,而是在全局静态区域。所以这里没有访问空地址的内容,故程序运行时正常。
而如果在Display()方法中访问了m_nVar1,编译连接全通过,发生运行时异常(存储空间受保护情况下)。
------解决方案--------------------
不得不说,楼上的分析得完全正确。
不过我还是实际验证了一下。
如果仅仅使用搂主的代码,在VC6中的确编译不过。
Deleting intermediate files and output files for project 'TC2 - Win32 Debug '.
--------------------Configuration: TC2 - Win32 Debug--------------------
Compiling...
StdAfx.cpp
Compiling...
TC2.cpp
tc2.cpp(13) : error C2065: 'printf ' : undeclared identifier
tc2.cpp(25) : error C2065: 'NULL ' : undeclared identifier
tc2.cpp(25) : error C2440: 'initializing ' : cannot convert from 'int ' to 'class foo * '
Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
执行 cl.exe 时出错.
TC2.exe - 1 error(s), 0 warning(s)
加上#include <stdio.h> 就可以编译通过了。
当然,可能这个不是楼主的本意。
------解决方案--------------------
俺选D
------解决方案--------------------
1. 我测试了一下. 在 xp + vc-7_1 的环境下. 加上 #include <iostream> 后, 正常编译连接, 正常运行.
2. 但是我还是选 B. 我的理由是, Display 不是一个静态函数. 应该需要一个对象的实例的呀.
3. 我能想象的是, Display 方法被隐式的当作了 implicitly static member. 这点让我很迷惑. 我的记忆中, 只有 4 个方法可以作为隐式的静态成员方法. 分别是
T::operator new
T::operator delete
T::operator new[]
T::operator delete[]
4. 另外, NULL 不是 C++ 标准的东西, 它是编译器厂商的实现方案. 目前的标准采用的是 0. 如下:
foo *p = 0; // 这样比较标准
C++0x 似乎有意要将引入 nullptr 作为关键字, 专门针对指针. 不过那是后话了.
5. mark一下. lz 的题目出的挺有意思. 坚持下去哦. 希望能把 C++ 的边边角角都扫扫干净.
------解决方案--------------------
zenny_chen(ACE Intercessor) 说得很不错
偶补充一个 :)
void Display()
{
if (this)
printf( " m_nVar1 is %d ", m_nVar1 );
}
这样,你或许可以看出是什么回事情了:)
这个函数访问了 m_nVar1 ,即使是 NULL
对象也不会出错
------解决方案--------------------