首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C语言 >

一个C语言指针有关问题

2012-10-25 
一个C语言指针问题今天重新拿起C语言的书学习学习,遇到了一个诡异的问题,开始不可理解,现在记录下整个分析

一个C语言指针问题
今天重新拿起C语言的书学习学习,遇到了一个诡异的问题,开始不可理解,现在记录下整个分析过程。
首先上代码:

#include <stdio.h>void strcopy(char *s, char *t){    while ((*s++ = *t++) != '\0')    ;}int main(){    int i = 3;    char a[] = "abcdefg";    char *p;    strcopy(p, a);    printf("%d\n",i);}

我估计大多数人看到这个程序都会认为会打印出3,但是结果出乎意料:


于是我分别做了两次修改,都使程序正常了。
第一次,我把strcopy函数注释掉了
#include <stdio.h>void strcopy(char *s, char *t){    while ((*s++ = *t++) != '\0')    ;}int main(){    int i = 3;    char a[] = "abcdefg";    char *p;    //strcopy(p, a);    printf("%d\n",i);}

打印结果是3.
第二次,我把int i = 3;移动p指针下面定义:
#include <stdio.h>void strcopy(char *s, char *t){    while ((*s++ = *t++) != '\0')    ;}int main(){    char a[] = "abcdefg";    char *p;    int i = 3;    strcopy(p, a);    printf("%d\n",i);}

也得到了正确的结果。
于是我用C free对原来的程序进行调试。

找到变量i的内存地址,可知其存放的是00000003,也就是数字3。
接着我执行strcopy方法后,就出状况了:


结果表明字符串被拷贝到了变量i的内存地址处。我对i处内存的内容进行十六进制转十进制,64636261转十进制后正好是1684234849.也就是这个诡异的输出结果。
综合以上的分析,所得结果如下:
#include <stdio.h>void strcopy(char *s, char *t){    while ((*s++ = *t++) != '\0')    ;}int main(){    int i = 3;    //定义int型变量i,分配内存空间,并赋值    char a[] = "abcdefg";    char *p;    //定义指针p,并为初始化指针的位置,在此程序中p默认指向了i的地址    strcopy(p, a);    printf("%d\n",i);}

现在真相大白了,不过任然让我疑惑的在指针p被定义的时候,p的默认指向地址是否有规律可循呢?任旧是个疑问,还请看到这篇文章的各位童鞋指点一二。
不过这个程序本来就是写的有问题,C语言的内存分配果然很容易出错(⊙o⊙)…
我想正确的程序应该是这样的...
#include <stdio.h>void strcopy(char *s, char *t){    while ((*s++ = *t++) != '\0')    ;}int main(){    int i = 3;    char a[] = "abcdefg";    char *p = (char *)malloc(sizeof(a));    //给指针分配新的内存空间    strcopy(p, a);    printf("%d\n",i);}

另外,搜索了下,函数malloc()和函数calloc() 的主要区别是前者不能初始化所分配的内存空间,而后者能。CString ReadSomething(){ CString str; str.format(_T("%s"),"abcdef"); return str;}

你会发现有时候是abcdef,有时候是别的东东,这是java程序员写C/C++容易犯的错误 11 楼 williamy 2011-06-27   感觉 这跟中国的"走进科学"节目一样,
"这个是一个很诡异的C程序"
诡异在何处?
哦,楼主还拿出那么多科学证明过程,
最后的结果是,楼主原来是C语言不好

就像中国西部发生的一件很诡异的事情
一个农民家每天早晨起来都发现鞋子再床上,
经过专家研究,探讨,最后得出结论是,这个农民晚上没洗脚,并且是穿鞋子睡觉的


12 楼 jackra 2011-06-27   没有分配空间吗?
刚声明完的指针,会指向那个地址呢?这个问题得问编译器。 13 楼 eman 2011-06-27   williamy 写道感觉 这跟中国的"走进科学"节目一样,
"这个是一个很诡异的C程序"
诡异在何处?
哦,楼主还拿出那么多科学证明过程,
最后的结果是,楼主原来是C语言不好

就像中国西部发生的一件很诡异的事情
一个农民家每天早晨起来都发现鞋子再床上,
经过专家研究,探讨,最后得出结论是,这个农民晚上没洗脚,并且是穿鞋子睡觉的




哈哈,lz应该把《c和指针》多看几遍,野指针而已,基础不扎实,觉得什么都诡异。 14 楼 ppgunjack 2011-06-27   这个如果情况属实,不是野指针这么简单,栈上分配的指针刚好内容是栈上其他变量的地址,这个巧合概率太低
原来以为是优化导致的栈上变量被寄存器替换导致i,p可能用的同一个寄存器,但是实际编译发觉也不可能出现这种情况 15 楼 jkdntc 2011-06-27   pujia12345 写道新手 小白吧

p你只定义了一个指针,没有分配变量空间,运行中无意占用了i的空间。

这都不清楚?

一般这样
char str[128];
char * p=str;
strcpy(p,a);


估计是老师教的不好,指针是c语言基础一定要扎实. 16 楼 panggezi 2011-06-27   坑爹啊,这C程序写的,一个野指针,你就敢当参数传进去,写内存,还诡异? 17 楼 luckwangjing 2011-06-27   看到这个帖子让我想起了以前遇到的一个问题!那个问题让我加深了对C语言指针初始化的必要性意识。

首先是定义了一个指针,是忘记了指针初始化。后面经过一系列的操作之后,对该指针进行释放,结果把别的结构体释放掉了一半,这个问题就很奇怪了,被释放的结构体数据错乱了,在经过几天的努力,终于找到了这个问题!当时就真的非常郁闷!后来就习惯性的在定义任何指针的时候都给他置空!

其实LZ这个问题没什么研究的!关于这个指针默认值是怎么分配的,这个和编译器有关,和上下文也有关! 18 楼 dbaspider 2011-06-27   哎,典型的缓冲区溢出造成的。。。 19 楼 rokuan 2011-06-27   (⊙o⊙)…只是学习过程中碰到的问题做个记录,各位轻拍,还请给新手多一些耐心和指教,不过这个标题的确起的很烂 20 楼 chimer 2011-06-27   野指针本来就不可预料吧 21 楼 qforever 2011-06-27   所有的指针都要初始化,没有初始值,也需要设NULL,不然后患无穷啊 22 楼 night_stalker 2011-06-28   ray_linn 写道2. t根本就是未分配的地址,这样的拷贝根本随编译器的开心在任一地址中乱写。 微软vc的保护函数在这一方面做出了改进,但是可惜没有成为标准,否则用strcpy_s就能预防这种情况。glibc就比较陈旧了。


讨厌的地方是总提示 strcpy deprecated ...
有时我就是想用 strcpy 啊 ... 23 楼 ray_linn 2011-06-28   night_stalker 写道ray_linn 写道2. t根本就是未分配的地址,这样的拷贝根本随编译器的开心在任一地址中乱写。 微软vc的保护函数在这一方面做出了改进,但是可惜没有成为标准,否则用strcpy_s就能预防这种情况。glibc就比较陈旧了。


讨厌的地方是总提示 strcpy deprecated ...
有时我就是想用 strcpy 啊 ...


这个warning是可以屏蔽的吧,不过我还是会尽量用_s,至少可以防止缓冲区溢出。 24 楼 地狱牢笼 2011-06-29   rokuan 写道liusondark 写道为什么我用VC++运行不了
不太清楚,vc我不太会用,还是比较习惯gcc编译,C Free用的比较顺手
lz有zb的嫌疑 25 楼 rokuan 2011-06-29   地狱牢笼 写道rokuan 写道liusondark 写道为什么我用VC++运行不了
不太清楚,vc我不太会用,还是比较习惯gcc编译,C Free用的比较顺手
lz有zb的嫌疑恭喜你,答对了 26 楼 kakueiken 2011-06-30   野指针,值是不可预测的。
不过由于函数堆栈是向上增加的。所以。

char x[]="abcde"
char *p;

打印p的值,很可能吧x的值打印出来了。

函数一开始为函数内部变量分配内存。
比如 上述,sp-7
那么p的地址是 ebp-4
x的地址是ebp-5
由于printf是顺序打印的所以会导致这个原因吧。。。

以上用IDA反汇编一下,可以清楚的看到。 27 楼 jinleileiking 2011-06-30   chimer 写道野指针本来就不可预料吧

一些好的编程习惯可以避免野指针 28 楼 yangguo 2011-06-30   学习和研究态度都不错,很有潜力,给你投个精华。

热点排行