关于语句 while((*s++ = *t++) != '\0') 运算顺序的疑问

字符串拷贝操作test1

void test1(char *s, char *t) 
{
    while((*s++ = *t++) != '\0')
    ;   
}

void test2(char *s, char *t) 
{
    while((*(s++) = *(t++)) != '\0')
    ;   
}

01 这两个函数都可以完成操作,但是test2中(s++)和(t++)为什么没有在 (*s = *t) 之前执行?(如果在赋值之前执行应该第一个字符无法被复制才对吧)

02 网上有对test1做出解释

void test3(char *s, char *t) 
{
    while(*t != 0)
    {
        *s = *t;   
        s++;                
        t++;                          
    } 
}

为什么是先判断 (t != 0) 之后,再进行赋值操作,再进行自增运算 (不是先赋值再判断s的值是否等于0?)

03 自己理解的test1执行顺序,这样理解是否正确

void test4(char *s, char *t) 
{
    while(1)
    {
        *s = *t;
        s++;
        t++;
        if(*s != 0)
            break;
    }
}
阅读 7k
5 个回答

谢邀

01 参考我的这个回答 C语言中*s++ = *t++ 是怎么一种赋值过程

02 这个不完全等效,你的理解是对的

03 你的这个写法也是不对的,你给出的逻辑是s++之后再判断*s == 0(你原文写的!=应该是写错了),这与原代码逻辑不同

等效test1的逻辑是

void test5(char *s, char *t) 
{ 
    char *temp;
    while(1) {
        *temp = (*s = *t);   // 赋值表达式 '*s = *t' 也是表达式,其计算结果等于'*t',
        s += 1;
        t += 1;
        if(*temp != '\0') 
            ;
        else
            break;
    }
}

<c和指针中>是这么写的:
图片描述

所以按这种解释的话,不管s++t++有没有括号,都是一样的.
但是根据@spacelan的运行结果,不知道现代编译器是不是简化步骤了,总之效果是一样的,讨论下去没啥意思

同初学者,一起讨论下。
在我看来循环条件里面的++运算都是相当于循环语句执行完之后执行,所以你的if要写在两个++的前面。
不过一点,'\0'不要总写成0, 类型不一样,会有个强制转换的过程,当你真的希望转换的时候就写出来,这种隐式转换有时候会出现意想不到的问题的。
其实有debug工具可以看每一步执行之后各个变量的值,可以帮助判断。

  1. 自增运算符前置,在表达式计算之前先自增;自增运算符后置,在表达式计算结束后自增。
    自减同理。。。

  2. 没有拷贝到'\0'

  3. 同样没有拷贝到'\0'

关于test1,为什么先while(*t != '\0'):
这样应该是为了避免当t是一个空字符串的情况。如果是个空字符串,*t++的值是一个不确定的值。

*s++*(s++) 的结合顺序都是从右到左。 所以()可以忽略。
欢迎斧正

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏