标题:继续请教我之前一个小程序的问题,短信可能不容易被发现
取消只看楼主
a271885843
Rank: 2
等 级:论坛游民
帖 子:291
专家分:58
注 册:2011-11-24
结帖率:84.38%
已结贴  问题点数:10 回复次数:6 
继续请教我之前一个小程序的问题,短信可能不容易被发现
#include<stdlib.h>
#include<stdio.h>

int main()
{

    char a[1000];
    char *p;

    gets(a);
    p=a;


    printf("%s\n",p);
    system("pause");
    return 0;
}

这是 论坛里一朋友对我https://bbs.bccn.net/viewthread.php?tid=357272&extra=&page=1 这个帖子的回复。我想问下,我的意思是*p输出,为什么在这里用p呢,还有就是为什么我用*p之后,编译没问题,正常通过,但一运行exe的时候就会出现内存出错的提示呢
搜索更多相关主题的帖子: 短信 include system return 
2011-12-08 22:17
a271885843
Rank: 2
等 级:论坛游民
帖 子:291
专家分:58
注 册:2011-11-24
得分:0 
以下是引用a271885843在2011-12-8 22:17:36的发言:

#include
#include

int main()
{

    char a[1000];
    char *p;

    gets(a);
    p=a;


    printf("%s\n",p);
    system("pause");
    return 0;
}

这是 论坛里一朋友对我https://bbs.bccn.net/viewthread.php?tid=357272&extra=&page=1 这个帖子的回复。我想问下,我的意思是*p输出,为什么在这里用p呢,还有就是为什么我用*p之后,编译没问题,正常通过,但一运行exe的时候就会出现内存出错的提示呢
你说了我就记住了。是不?

认为事物非黑即白是缺智慧的表现……
2011-12-09 20:03
a271885843
Rank: 2
等 级:论坛游民
帖 子:291
专家分:58
注 册:2011-11-24
得分:0 
自己定上去,我自己没多少时间去看书了。真的。群里好心的哥哥姐姐帮我解答一下吧。3Q

认为事物非黑即白是缺智慧的表现……
2011-12-09 20:06
a271885843
Rank: 2
等 级:论坛游民
帖 子:291
专家分:58
注 册:2011-11-24
得分:0 
以下是引用TonyDeng在2011-12-9 20:54:21的发言:

有在这里顶的时间都把书看完了,早解决了。
明白了。其实不是我不去看书,而是看了书之后我产生了疑惑。char *p;定义字符串指针,其作用是来存放字符串首地址或者数组的首地址的,比如直接将将字符串赋值给它,如p="c programe langeuge",p就存放这句话的首地址,然后如果是printf("%s\n",p);那么表示从p所存放的首地址开始将此字符串全部输出,但如果是printf("%\n",*p);那么表示输出指针p所指的那个地址存放的单个字符,如全部输出此句话,要加上
  while(*p!='\0')
    {
        printf("%c",*p);
        p++;
    }
才能将此句全部输出,但我的疑问又有了,下面程序运行怎么可以编译通过,输入一段字符按回车,没有输出第一个字符啊,而且显示内存出错,这才是我想问的。
#include<stdlib.h>
#include<stdio.h>
int main()
{
  char a[1000];
    char *p;
    gets(a);
     p=a;
  printf("%s\n",*p);
 }

认为事物非黑即白是缺智慧的表现……
2011-12-09 22:25
a271885843
Rank: 2
等 级:论坛游民
帖 子:291
专家分:58
注 册:2011-11-24
得分:0 
以下是引用embed_xuel在2011-12-9 22:34:35的发言:

你自己都写了,你打印*p用%c可以,用%s就出错了
哎。谢谢你。

认为事物非黑即白是缺智慧的表现……
2011-12-09 22:53
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
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



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-357340-1-1.html




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

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