黑马程序员技术交流社区

标题: c语言问题求解答 [打印本页]

作者: 吴小婷    时间: 2015-3-30 21:32
标题: c语言问题求解答
#include <stdio.h>

//计算并返回字符串长度
int string_len(char *s)
{
    int count = 0;//纪录字符串长度
    while (*s++) {// 当当前字符为0,即(*s!=0)时,字符串长度加1,并移动至下一个字符(s++)
        count++;
    }

    return count;//返回字符串长度count;
}

int main()
{

    int size=string_len("i");

    printf("字符串的长度是%d\n",size);//打印字符串长度

    return 0;
}

上面是计算并返回字符串长度的程序,其中
while (*s++)
{
    count++;
}
这一段,s可以理解为指向字符串首字符的指针,当第一次进入循环的时候,(*s++)应该理解为访问第二个字符,那么循环的判断句则是从判断第二个字符开始,并没有判断第一个字符,那么输出的长度应该比真实的少1,但是运行的结果并没有如此,而是字符正真的长度,为什么呢?  我的理解哪里出错了呢?


8102D928-313E-4652-A06B-15150DD6F4AF.png (92.71 KB, 下载次数: 59)

8102D928-313E-4652-A06B-15150DD6F4AF.png

作者: Himoriarty    时间: 2015-3-30 21:32
*s++和++*s是不一样的,你说的是++*s的情况,先将*s加1之后返回++*s的结果,*s++是先返回*s进入判断语句时的值,判断结束之后再给*s加1。然后就进入while内部语句执行了。你可以在while体内加一句printf("output character  %s",s-1);就可以看出第一次访问的是第几个字符。
作者: 吴小婷    时间: 2015-3-30 22:28
Himoriarty 发表于 2015-3-30 21:58
*s++和++*s是不一样的,你说的是++*s的情况,先将*s加1之后返回++*s的结果,*s++是先返回*s进入判断语句时 ...

感谢~!
作者: 倾城只为你来    时间: 2015-3-30 22:36
回答的挺好的
作者: daydream    时间: 2015-3-30 22:52
按题主的思路来讲的话,*s++的操作相当于进行了如下两步:
1.进行s++;
2.对s进行解引用。
事实上正好相反,我们知道,运算符*与++的优先级相同且为右结合,*s++与*(s++)是一样的,这个式子在执行时可以用以下两步来理解:
1.tmp = *s,此值用于循环条件的判断。
2.在判断结束后,进入循环体前更新s的值,即将指向下一个字符的位置。
注:这里涉及到表达式的副作用以及顺序点的相关内容,题主可以查一下。
另外,与*s++类似的操作还有++*s,*++s等。测试如下:
测试环境:centOS6.5 (32位) + gcc-4.4.7

  1. #include <stdio.h>

  2. int main(int argc, char *argv[])
  3. {
  4.         char a[] = "1234567";
  5.         char *p = a;                //初始时p指向[0]
  6.         char ch1 = *p++;        //执行完后p指向[1]
  7.         char ch2 = *(p++);      //执行完后p指向[2]
  8.         char ch3 = *++p;        //p先由[2]移到[3],然后再解引用
  9.         char ch4 = ++*p;        //取出[3]的值并加1,然后返回给ch4
  10.         char ch5 = (*p)++;      //取出[3]的值,将其返回给ch5,然后再将值加1
  11.         char ch6 = *(++p);      //将p由[3]移到[4],然后解其引用,即取出[4]处的值
  12.         char ch7 = ++(*p);      //取出[4]处的值并将其加1
  13.         printf("ch1 = %c\n", ch1); //1
  14.         printf("ch2 = %c\n", ch2); //2
  15.         printf("ch3 = %c\n", ch3); //4
  16.         printf("ch4 = %c\n", ch4); //5
  17.         printf("ch5 = %c\n", ch5); //5
  18.         printf("ch6 = %c\n", ch6); //5
  19.         printf("ch7 = %c\n", ch7); //6
  20.         printf("%s\n", a);              //1236667
  21.         return 0;
  22. }
复制代码

作者: 1048    时间: 2015-4-1 12:03
学习了。。。。。。
作者: Nicholas_Chow    时间: 2015-4-1 22:36
举个例子
int i = 3;
那么i++和++i运行之后i都要变成4
不同的是i++是先取i的值,再把i加1,i++这句自身的值是3
++i是先把i加1,再把新的i的值取出,++i这句自身的值是4

希望有助你理解你的问题
作者: jonk    时间: 2015-4-5 09:54
*s 指针指向的是字符串的第一个字符(比如字符串是“ijjsdsjhj”),那么s++是先取后加,实质上 whlie(i != 0,而不是while(j!=0))因此他会执行判断字符串的第一个值是否等于0,显然不等0,那么count就会执行count = count + 1 ,所以他出来的就是字符串的真实值;
作者: Angelsmile    时间: 2015-4-5 19:46
s++先运算,再自加1;++s,先自加1,再运算。
作者: 开山斧    时间: 2015-4-7 16:51
本帖最后由 开山斧 于 2015-4-7 17:00 编辑

(*s++)应该理解为访问第1个字符,要理解s++和++s的区别,s++表达式的值仍然为s,而s的值为s+1,如s=1,那么   s++;表达式的值为1,s的值为2。++s中++s; 表达式的值为s+1,即如s=1,那么++s;表达式的值为2 ,s的值也为2。所以(*s++)的值等于*s。
作者: windform    时间: 2015-4-12 17:49
*S++ 是先取S当前所指向的内存的值,然后再将S指向下一个存储单元。
作者: lvzhehappy    时间: 2015-4-16 15:11
你们忘记了一个c语言字符串的重点,c语言字符串都是以'\0'结尾为标志的,所以*s++执行过后,*(s+1)='\0';这个时候不为空,在循环体中还得执行一次,因此你们得到答案的才是1,而strlen函数计算的有效的字符个数,并不统计‘\0’.
如果不相信你可以修改下
while((*s++)!='\0')
{
count++;
}
作者: 杨凯瑞    时间: 2015-6-11 10:07
管理员屏蔽啦

作者: 甘心情愿    时间: 2015-7-28 22:03





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2