| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 842 人关注过本帖
标题:继续请教我之前一个小程序的问题,短信可能不容易被发现
只看楼主 加入收藏
a271885843
Rank: 2
等 级:论坛游民
帖 子:291
专家分:58
注 册:2011-11-24
收藏
得分:0 
以下是引用TonyDeng在2011-12-9 22:52:01的发言:

首先纠正你一个概念:char *p不是定义字符串指针,而是定义一个指针,而且这个指针所指向的数据是char类型的。当定义char *p的时候,指针p是可以运动的,随着它的移动,每个*p所取得的数据跟着变化。但是要注意,指针与数组是有区别的,定义数组char a[1000]时,a虽然是首地址指针,但a无法像p那样运动,你可以a+2或*(a+2),但无法a += 2,而p可以p += 2。因此,要定义数组,不要只考虑char *p,那不是数组,而只是单个指针。

然后,解释你现在的问题。函数printf()是别人写好的代码,当使用格式码"%s"的时候,函数预期匹配的参数是一个字符数组的入口指针,而且这个字符数组应该按照C语言的cz规范构造(即有字符'\0'作结束标志)。好了,现在看你的printf("%s", *p),函数认为,*p是数组入口,也就是说,它把现在指针p的对象值作为了地址,而不是把p作为地址。因此,函数到地址为*p的地方寻找数据,对char数据来说,其值小于255,这个地址值往往是程序的保护区,何况,从这个地址开始往后搜寻,printf()函数经常很难遇到'\0'终止自己的行动,后果是无法猜测的。也就是说,p才是你希望的数组入口,*p不是。

函数printf()所预期的东西,不归编译器管辖,编译器绝对不会验证printf("%d", "hello")这样的问题,因为验证传入数据是否正确是函数编写者自己的事,偏偏写printf()和scanf()函数的程序员是不作这种验证的,他假定使用这个函数的人自己保证输入正确的数据。这是一种很可怕的编程风格。
嗯。更谢谢你。

认为事物非黑即白是缺智慧的表现……
2011-12-09 22:57
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
编译器为什么不警告?这种情况类似于你写如下的函数:

程序代码:
int fun(int a, int b)
{
    return a / b;
}


编译器编译时,它只检查你的调用代码是否满足数据类型的规定,比如fun(1,1.5)就必定错了,因为1.5不是int类型。但对fun(1,0)的调用,它就不知道了,此时,程序在运行时崩溃。对编程的人来说,在函数fun()中检查b不能为零,是程序员的责任,你不写,编译器不会负责的。其实很多C程序的所谓高效,往往是牺牲了这方面的代码带来的,如果你把检查b是否为零的代码写上去,函数体就长了许多,尽管b=0的机会微乎其微,很多不负责任的程序员为了高效,经常冒险不写这样的代码。这是要不得的编程习惯,千万不要养成这样的编程风格!printf()和scanf()这样的东西,给多少人带来麻烦,就是这样的原因。

gets()这样的函数也一样,你定义a[100],满以为敲键盘的人会在敲99个字符之前停止,那是不切实际的假设,而且一旦gets()函数执行,它也无法抗拒用户敲太多的字符给自己。正确的做法是你自己写一个接受输入的函数,有办法拦阻用户输入太多字符的,如果没有这样的东西,你的程序交出去供用户使用,只能讨骂,因为它经常出错、崩溃。你没有任何理由要求用户自己注意,用户只会说你的程序笨。

总的说来就是,编译器报错是一定有问题,但编译器不报错却未必没有问题,不报错的时候出的问题才更令人头痛、也往往是大问题。能让人整个程序推倒重来的,十有八九是运行时偶尔出错的那种。

[ 本帖最后由 TonyDeng 于 2011-12-9 23:28 编辑 ]

授人以渔,不授人以鱼。
2011-12-09 23:10
a271885843
Rank: 2
等 级:论坛游民
帖 子:291
专家分:58
注 册:2011-11-24
收藏
得分:0 
以下是引用TonyDeng在2011-12-9 23:10:24的发言:

编译器为什么不警告?这种情况类似于你写如下的函数:

 
int fun(int a, int b)
{
    return a / b;
}


编译器编译时,它只检查你的调用代码是否满足数据类型的规定,比如fun(1,1.5)就必定错了,因为1.5不是int类型。但对fun(1,0)的调用,它就不知道了,此时,程序在运行时崩溃。对编程的人来说,在函数fun()中检查b不能为零,是程序员的责任,你不写,编译器不会负责的。其实很多C程序的所谓高效,往往是牺牲了这方面的代码带来的,如果你把检查b是否为零的代码写上去,函数体就长了许多,尽管b=0的机会微乎其微,很多不负责任的程序员为了高效,经常冒险不写这样的代码。这是要不得的编程习惯,千万不要养成这样的编程风格!printf()和scanf()这样的东西,给多少人带来麻烦,就是这样的原因。

gets()这样的函数也一样,你定义a[100],满以为敲键盘的人会在敲99个字符之前停止,那是不切实际的假设,而且一旦gets()函数执行,它也无法抗拒用户敲太多的字符给自己。正确的做法是你自己写一个接受输入的函数,有办法拦阻用户输入太多字符的,如果没有这样的东西,你的程序交出去供用户使用,只能讨骂,因为它经常出错、崩溃。你没有任何理由要求用户自己注意,用户只会说你的程序笨。
嗯。谢谢前辈指导,C菜晚辈受教了。

认为事物非黑即白是缺智慧的表现……
2011-12-09 23:28
心灵百合
Rank: 5Rank: 5
等 级:职业侠客
帖 子:215
专家分:367
注 册:2011-3-30
收藏
得分:2 
p=a改为p=&a[0];
2011-12-10 13:16
快速回复:继续请教我之前一个小程序的问题,短信可能不容易被发现
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.011354 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved