这个野指针不?为什么可以使用?

方紫涵 2012-10-23 02:40:01

#include<iostream>
#include<cstring>

using namespace std;

class A
{
public:
void prinfs()
{
cout<<"aaaaa"<<endl;
}
};



int main( )
{
A *a;
a->prinfs();
return 0;
}


A *a;
a->prinfs(); //这个a是个野指针不?为什么能够执行阿?

在g++里面

work/ctest$ g++ array.cpp -o 1
/work/ctest$ ./1
aaaaa
...全文
3271 83 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
83 条回复
切换为时间正序
请发表友善的回复…
发表回复
jilianglijie 2012-11-05
  • 打赏
  • 举报
回复
楼主我的理解如下: 对类方法的调用是直接对类中函数的调用; 对象对类中数据的方法是通过指针的方法进行访问的; 就以你的代码为例

#include<iostream> 
#include<cstring>
 
using namespace std;
 
class A
{
public:
    void prinfs()
    {
        cout<<"aaaaa"<<endl;
    }
};

int main( )
{
    A *a;
    a->prinfs();
    return 0;
}
其中调用a->printfs();其实是对该类中方法的直接调用,而你没有直接使用到this指针因此系统不报错。 我有以下佐证(windows下验证):

	A *a;
	a->prinfs();
004114E5  cmp         byte ptr [ebp-0D1h],0 
004114EC  jne         wmain+3Bh (4114FBh) 
004114EE  push        offset  (411519h) 
004114F3  call        @ILT+250(__RTC_UninitUse) (4110FFh) 
004114F8  add         esp,4 
004114FB  mov         ecx,dword ptr [a] 
004114FE  call        Printer::Printer (411267h) 
以上是执行a->printfs();的汇编代码,当然在这段代码中是会出错的,由于没有进行初始化因此编译器执行__RTC_UninitUse来进行检查,所以代码执行到这就会发生异常,但继续执行还是可以输出‘aaaaa’。 我后来给指针赋值为NULL汇编代码如下

	A *a= NULL;
004114DE  mov         dword ptr [a],0 
	a->prinfs();
004114E5  mov         ecx,dword ptr [a] 
004114E8  call        Printer::Printer (411267h) 
执行过程没有发生异常,可以看到寄存器ecx中保存的即时对象指针。 因此你要的答案是: 是野指针。因为调用对象的方法是直接调用类中函数的方法来实现的,在这个例子中是可以使用的。 提示: 如果你在该方法中使用了类中的其他成员变量,则会造成不可预期的错误。建议修改此类错误。
ysu108 2012-11-05
  • 打赏
  • 举报
回复
函数是是属于整个类的,并不是某个对象的,就跟static变量一样。这样使用没有涉及到this的解引用,函数没有使用任何数据成员,可以直接调用的~
再见理想~ 2012-11-05
  • 打赏
  • 举报
回复
没法运行,野指针
Vonger 2012-10-29
  • 打赏
  • 举报
回复
其实也没什么,C++的函数都是导出成类似C的符号使用的,所以你那个不仅能编译还能运行
你的A下的print在编译后obj内其实是一个类似于这样的C函数 A_print(void, void *this)
这个可以用dependswalker之类的工具查看C++封装的DLL就可以看到
函数里面没有用到this指针,所以也就不存在什么野指针,照样不会崩溃
俯瞰夕阳 2012-10-28
  • 打赏
  • 举报
回复
好多大神啊
江南刹 2012-10-28
  • 打赏
  • 举报
回复
指针最忌讳没有赋值就开始用了,int *p;
cout<<*p<<endl;
由于p指向的空间内容未知不确定,所以。。。
渔丶 2012-10-27
  • 打赏
  • 举报
回复
受教了,!各位大神论述的很清楚!
方紫涵 2012-10-27
  • 打赏
  • 举报
回复
这个砖头引来这么多玉阿!
Tyun2012 2012-10-27
  • 打赏
  • 举报
回复
8楼+25楼的理论说得比较清楚了,貌似53楼的代码解说不错,不过确实说得蛮乱。就你的问题回答,那是个野指针,一般编译器都能运行。简单说,野指针也是个指针,只是指向的目标不明确,是一片无意义的内存空间。要是编译器严格点,就可能报错,一般都不会的。
这样做是很危险的,就像拿一把枪,乱扫一样!指不定哪儿有个人,就被你打死了!
ganjianh8 2012-10-27
  • 打赏
  • 举报
回复
看我的博客
帅虫虫 2012-10-27
  • 打赏
  • 举报
回复
成员函数(不含静态成员函数)和普通函数的区别就在于成员函数有一个隐藏的参数this。
你代码中的成员函数里(prinfs)里没有访问this指针,自然就不会报错。
yzh198769 2012-10-27
  • 打赏
  • 举报
回复
这样写很不规范
bean11222 2012-10-27
  • 打赏
  • 举报
回复
这个很好理解,因为你只申明了一个指针变量(32位是4字节, 可以把它当整型看都没问题),而指针变量所指向的对象并没有初始化。。。。
已毕业程序员 2012-10-26
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]

引用 2 楼 的回复:

是野指针。
你只是生命了一个指针,却没有给它分配内存空间。
C/C++ code

int main( )
{
A *a = new A();
a->prinfs();
delete a;
return 0;
}

看我的运行结果,并没有new一个实例出来阿,但是确实是可以运行的阿/
[/Quote]

你已经new出一个实例了,一个无名的实例,当然可能运行
我爱吃火锅 2012-10-26
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]

是野指针。
你只是生命了一个指针,却没有给它分配内存空间。
C/C++ code

int main( )
{
A *a = new A();
a->prinfs();
delete a;
return 0;
}
[/Quote]
二楼说的对,确实是野指针。
yisikaipu 2012-10-26
  • 打赏
  • 举报
回复
[Quote=引用 60 楼 的回复:]

引用 59 楼 的回复:
If E1 has the type “pointer to class X,” then the expression E1->E2 is converted to the equivalent form (*(E1)).E2;
意思是 a->prinfs(); 其实是要转换为 (*a).printfs();
呃 这里应该没有表达要转换为的意思
不过 的确……
[/Quote]

不妨用 call a member function on a null pointer 搜搜,不难发现网上但凡读标准的,都认为用空指针调用成员函数是未定义行为。换成野指针/悬垂指针,道理类似

lin5161678 2012-10-26
  • 打赏
  • 举报
回复
[Quote=引用 59 楼 的回复:]
If E1 has the type “pointer to class X,” then the expression E1->E2 is converted to the equivalent form (*(E1)).E2;
意思是 a->prinfs(); 其实是要转换为 (*a).printfs();[/Quote]
呃 这里应该没有表达要转换为的意思
不过 的确说了 两者是等价的
那么 a->.... 和 (*a)....表达的应该是一样的
能写成a->的就能写成(*a).的形式
(*a). 有一个对指针*求值的操作 嗯 的确是看到未定义行为了
恩恩 同意你的看法 未定义行为
yisikaipu 2012-10-26
  • 打赏
  • 举报
回复
[Quote=引用 58 楼 的回复:]

看了半天 觉得 这里主要的问题就是
一个类的不同对象的同一个成员函数是不是在一个位置
如果这个在标准中有明确指出的 是同一个函数
那么 A* a;a->print();就应该没什么问题
[/Quote]

诸如这样的写法
((A*)0)->printfs()
的确是很常见的,但不合标准

我在#40楼给出了标准有关这种行为的规定

如果我理解错了,请一定给指正
lin5161678 2012-10-26
  • 打赏
  • 举报
回复
看了半天 觉得 这里主要的问题就是
一个类的不同对象的同一个成员函数是不是在一个位置
如果这个在标准中有明确指出的 是同一个函数
那么 A* a;a->print();就应该没什么问题
lanzhengpeng2 2012-10-26
  • 打赏
  • 举报
回复
因为prints()不是虚函数,所以,用C表达就是
A::prints(A*this)调用。是在编译时刻决定的调用哪个函数。而你在prints()并没有访问this,所以,也不会出一场。
如果prints是virtual的,则,用C表达就是
a->vtable[prints_index](A* this).
这样,因为在求vtable的时候,a是野指针,就会导致异常。
加载更多回复(62)
1. C 语言中的指针和内存泄漏 5 2. C语言难点分析整理 10 3. C语言难点 18 4. C/C++实现冒泡排序算法 32 5. C++中指针和引用的区别 35 6. const char*, char const*, char*const的区别 36 7. C中可变参数函数实现 38 8. C程序内存中组成部分 41 9. C编程拾粹 42 10. C语言中实现数组的动态增长 44 11. C语言中的位运算 46 12. 浮点数的存储格式: 50 13. 位域 58 14. C语言函数二维数组传递方法 64 15. C语言复杂表达式的执行步骤 66 16. C语言字符串函数大全 68 17. C语言宏定义技巧 89 18. C语言实现动态数组 100 19. C语言笔试-运算符和表达式 104 20. C语言编程准则之稳定篇 107 21. C语言编程常见问题分析 108 22. C语言编程易犯毛病集合 112 23. C语言缺陷与陷阱(笔记) 119 24. C语言防止缓冲区溢出方法 126 25. C语言高效编程秘籍 128 26. C运算符优先级口诀 133 27. do/while(0)的妙用 134 28. exit()和return()的区别 140 29. exit子程序终止函数与return的差别 141 30. extern与static存储空间矛盾 145 31. PC-Lint与C\C++代码质量 147 32. spirntf函数使用大全 158 33. 二叉树的数据结构 167 34. 位运算应用口诀和实例 170 35. 内存对齐与ANSI C中struct内存布局 173 36. 冒泡和选择排序实现 180 37. 函数指针数组与返回数组指针的函数 186 38. 右左法则- 复杂指针解析 189 39. 回车和换行的区别 192 40. 堆和堆栈的区别 194 41. 堆和堆栈的区别 198 42. 如何写出专业的C头文件 202 43. 打造最快的Hash表 207 44. 指针与数组学习笔记 222 45. 数组不是指针 224 46. 标准C中字符串分割的方法 228 47. 汉诺塔源码 231 48. 洗牌算法 234 49. 深入理解C语言指针的奥秘 236 50. 游戏外挂的编写原理 254 51. 程序实例分析-为什么会陷入死循环 258 52. 空指针究竟指向了内存的哪个地方 260 53. 算术表达式的计算 265 54. 结构体对齐的具体含义 269 55. 连连看AI算法 274 56. 连连看寻路算法的思路 283 57. 重新认识:指向函数的指针 288 58. 链表的源码 291 59. 高质量的子程序 295 60. 高级C语言程序员测试必过的十六道最佳题目+答案详解 297 61. C语言常见错误 320 62. 超强的指针学习笔记 325 63. 程序员之路──关于代码风格 343 64. 指针、结构体、联合体的安全规范 346 65. C指针讲解 352 66. 关于指向指针的指针 368 67. C/C++ 误区一:void main() 373 68. C/C++ 误区二:fflush(stdin) 376 69. C/C++ 误区三:强制转换 malloc() 的返回值 380 70. C/C++ 误区四:char c = getchar(); 381 71. C/C++ 误区五:检查 new 的返回值 383 72. C 是 C++ 的子集吗? 384 73. C和C++的区别是什么? 387 74. 无条件循环 388 75. 产生随机数的方法 389 76. 顺序表及其操作 390 77. 单链表的实现及其操作 391 78. 双向链表 395 79. 程序员数据结构笔记 399 80. Hashtable和HashMap的区别 408 81. hash 表学习笔记 410 82. C程序设计常用算法源代码 412 83. C语言有头结点链表的经典实现 419 84. C语言惠通面试题 428 85. C语言常用宏定义 450

65,186

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧