以下是引用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()函数的程序员是不作这种验证的,他假定使用这个函数的人自己保证输入正确的数据。这是一种很可怕的编程风格。
嗯。更谢谢你。
首先纠正你一个概念: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()函数的程序员是不作这种验证的,他假定使用这个函数的人自己保证输入正确的数据。这是一种很可怕的编程风格。
认为事物非黑即白是缺智慧的表现……