`
rokuan
  • 浏览: 19710 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

一个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() 的主要区别是前者不能初始化所分配的内存空间,而后者能。
  • 大小: 2.7 KB
  • 大小: 18.7 KB
  • 大小: 18.7 KB
分享到:
评论
28 楼 yangguo 2011-06-30  
学习和研究态度都不错,很有潜力,给你投个精华。
27 楼 jinleileiking 2011-06-30  
chimer 写道
野指针本来就不可预料吧


一些好的编程习惯可以避免野指针
26 楼 kakueiken 2011-06-30  
野指针,值是不可预测的。
不过由于函数堆栈是向上增加的。所以。

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

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

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

以上用IDA反汇编一下,可以清楚的看到。
25 楼 rokuan 2011-06-29  
地狱牢笼 写道
rokuan 写道
liusondark 写道
为什么我用VC++运行不了

不太清楚,vc我不太会用,还是比较习惯gcc编译,C Free用的比较顺手

lz有zb的嫌疑
恭喜你,答对了
24 楼 地狱牢笼 2011-06-29  
rokuan 写道
liusondark 写道
为什么我用VC++运行不了

不太清楚,vc我不太会用,还是比较习惯gcc编译,C Free用的比较顺手

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


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



这个warning是可以屏蔽的吧,不过我还是会尽量用_s,至少可以防止缓冲区溢出。
22 楼 night_stalker 2011-06-28  
ray_linn 写道
2. t根本就是未分配的地址,这样的拷贝根本随编译器的开心在任一地址中乱写。 微软vc的保护函数在这一方面做出了改进,但是可惜没有成为标准,否则用strcpy_s就能预防这种情况。glibc就比较陈旧了。


讨厌的地方是总提示 strcpy deprecated ...
有时我就是想用 strcpy 啊 ...
21 楼 qforever 2011-06-27  
所有的指针都要初始化,没有初始值,也需要设NULL,不然后患无穷啊
20 楼 chimer 2011-06-27  
野指针本来就不可预料吧
19 楼 rokuan 2011-06-27  
(⊙o⊙)…只是学习过程中碰到的问题做个记录,各位轻拍,还请给新手多一些耐心和指教,不过这个标题的确起的很烂
18 楼 dbaspider 2011-06-27  
哎,典型的缓冲区溢出造成的。。。
17 楼 luckwangjing 2011-06-27  
看到这个帖子让我想起了以前遇到的一个问题!那个问题让我加深了对C语言指针初始化的必要性意识。

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

其实LZ这个问题没什么研究的!关于这个指针默认值是怎么分配的,这个和编译器有关,和上下文也有关!
16 楼 panggezi 2011-06-27  
坑爹啊,这C程序写的,一个野指针,你就敢当参数传进去,写内存,还诡异?
15 楼 jkdntc 2011-06-27  
pujia12345 写道
新手 小白吧

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

这都不清楚?

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



估计是老师教的不好,指针是c语言基础一定要扎实.
14 楼 ppgunjack 2011-06-27  
这个如果情况属实,不是野指针这么简单,栈上分配的指针刚好内容是栈上其他变量的地址,这个巧合概率太低
原来以为是优化导致的栈上变量被寄存器替换导致i,p可能用的同一个寄存器,但是实际编译发觉也不可能出现这种情况
13 楼 eman 2011-06-27  
williamy 写道
感觉 这跟中国的"走进科学"节目一样,
"这个是一个很诡异的C程序"
诡异在何处?
哦,楼主还拿出那么多科学证明过程,
最后的结果是,楼主原来是C语言不好

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




哈哈,lz应该把《c和指针》多看几遍,野指针而已,基础不扎实,觉得什么都诡异。
12 楼 jackra 2011-06-27  
没有分配空间吗?
刚声明完的指针,会指向那个地址呢?这个问题得问编译器。
11 楼 williamy 2011-06-27  
感觉 这跟中国的"走进科学"节目一样,
"这个是一个很诡异的C程序"
诡异在何处?
哦,楼主还拿出那么多科学证明过程,
最后的结果是,楼主原来是C语言不好

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


10 楼 ray_linn 2011-06-27  
一个容易犯的错误
CString ReadSomething()
{
   CString str;
   str.format(_T("%s"),"abcdef");
   return str;
}


你会发现有时候是abcdef,有时候是别的东东,这是java程序员写C/C++容易犯的错误
9 楼 silence1214 2011-06-27  
这个就是野指针吧。。。不能说是奇怪,这个情况可能在不同的编译器下出现的结果不一定相同。。你没初始化指针,那么指向哪都有可能的。。不过挺有意思的,让LZ加深了对指针初始化的意识的加强

相关推荐

Global site tag (gtag.js) - Google Analytics