关于while(*s++=*t++)语句问题

kewenpan 2010-01-30 09:41:29
引用:
===============================================================================================
yegaofei(踏雪而歌) 解释的不错!

while(*s++=*t++); 在语义上等同于(注意条件部分是一个=,不是2个):

while((*t) != 0){
*s = *t;
s++;
t++;
}

显然前者更紧凑,效率(可能)更高。


arrowcy(长弓手)把流程解释得很清楚了
我帮你再通俗说一遍:

while(*s++=*t++); 这个在程序员杂志中,可能先声明了s和t都是字符串指针吧
在执行的时候,实现了好几个逻辑,步骤如下:
⑴ *t 的赋值给 *s
⑵判断 *s 是否为真。如果为假,则跳出循环;否则继续执行第⑶步。因为字符串是以\0结尾的,遇到\0的时候,也就是*s为假,就跳出了字符串拷贝。
⑶ s 和 t 加 1,指向下一个地址,准备拷贝下一个字符。
==============================================================================================
有个问题 第一步(1)⑴ *t 的赋值给 *s 解释对吗?不用判断指针为空吗?
谢谢各位讨论
...全文
804 20 打赏 收藏 举报
写回复
20 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
kewenpan 2010-01-31
  • 打赏
  • 举报
回复
那应该就和这个有关系了。多谢大家!
4楼
有时候可以不用,由调用函数方确保指针不为空

一般会在前面加上
assert(s!= NULL && t != NULL);

debug 版检查指针是否为空,如是则报错退出 release版为效率考虑不检查
jackzhhuang 2010-01-30
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 lovesi3344 的回复:]
while(*s++=*t++); 

我很欣赏这一种做法,简洁又有健壮性

如果指针t为空指针
那么*t == 0
赋给*s后,*s也等于0  这时就是while(0), 则循环体是不会执行的

注:值为零的指针被称为空值指针,简称为空指针。
while(0) 即循环判断条件为假(false),  false的字面值为0

这样其实也省去了检验指针是否为空的情况
多帅的程序啊


[/Quote]

红字部分不多哦,t为空指针,*t立马奔溃。

while(*s++ = *t++);
仅在两指针有效才有用

基础类库设计者为效率一般不会判断指针是否有效,尽量的简洁完成任务就可以了,一般只是写断言。当然也有在debug模式下加入判断和断言,在release模式下则去掉判断的情况,看个人意见了。

因为调用者非常清楚自己的指针值是否为空,也只有调用者才清楚这件事,所以调用者有责任保证指针有效。
macrojj 2010-01-30
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 lovesi3344 的回复:]
while(*s++=*t++);

我很欣赏这一种做法,简洁又有健壮性

如果指针t为空指针
那么*t == 0
赋给*s后,*s也等于0  这时就是while(0), 则循环体是不会执行的

注:值为零的指针被称为空值指针,简称为空指针。
while(0) 即循环判断条件为假(false),  false的字面值为0

这样其实也省去了检验指针是否为空的情况
多帅的程序啊


[/Quote]
如果t为null 还是要++然后崩掉
lovesi3344 2010-01-30
  • 打赏
  • 举报
回复
while(*s++=*t++);

我很欣赏这一种做法,简洁又有健壮性

如果指针t为空指针
那么*t == 0
赋给*s后,*s也等于0 这时就是while(0), 则循环体是不会执行的

注:值为零的指针被称为空值指针,简称为空指针。
while(0) 即循环判断条件为假(false), false的字面值为0

这样其实也省去了检验指针是否为空的情况
多帅的程序啊

烽火楼 2010-01-30
  • 打赏
  • 举报
回复 1
两者不完全等价!
while(*s++=*t++); 是先赋值*t-->*s,然后s++,t++,最后将*s的值作为判断条件。

while((*t) != 0){ 先拿*t的值作为判断条件
*s = *t; //再赋值
s++; //最后 自增
t++;
}

想想执行完的结果: 假如是字符串的拷贝,那么
(1)前者肯定将‘\0’赋给*s了,而后者没有;
(2)退出循环时,前者的s和t都指向‘\0’的后一个位置;而后者的t指向‘\0’,s与t同步,但没有获得‘\0’
(3)若在其后加上一句prinf("%s\n",s); 前者输出没有问题,后者输出可能出现问题(除非之前对s的每个位置都置0)
wangxipu 2010-01-30
  • 打赏
  • 举报
回复
窃以为0,NULL,'\0'三者还是有差别的
macrojj 2010-01-30
  • 打赏
  • 举报
回复
我觉得 第二种比较好。
zhyrs 2010-01-30
  • 打赏
  • 举报
回复
学习了。。。
lovesi3344 2010-01-30
  • 打赏
  • 举报
回复
没初始化的指针是野指针,空悬指针,悬浮指针
当然不是0

如你所述,char *p = NULL;//C语言喜欢用NULL,以明确是指针
或者char *p = 0;// C++喜欢用简单的0表示空指针
而NULL和0都表示指针为空

值为零的指针被称为空指针

第二,要注意 void *p; //被称为“通用指针”(generic pointer )
通用指针与空指针是不同的概念

[Quote=引用 18 楼 kewenpan 的回复:]
引用 10 楼 lovesi3344 的回复
注:值为零的指针被称为空值指针,简称为空指针。
while(0)

1: char* k = NULL;
define NULL 0  //C的定义方式
define NULL (void *)0  //C++的定义方式
定义并初始化为NULL可以理解上面

2 char* k; 没有初始化指针也一定为0吗?
非常感谢大家热情讨论!谢谢!

[/Quote]
开心的卡夫卡 2010-01-30
  • 打赏
  • 举报
回复
上面的代码只考虑了t中的内容是否为空,但并没有考虑会不会t = 0(NULL)
如果下面 char* t= 0;
char* s=new char[7];
while(*s++=*t++);
仍然会死掉!
如同楼上所说
一般都添加assert来先确定!
kewenpan 2010-01-30
  • 打赏
  • 举报
回复
引用 10 楼 lovesi3344 的回复
注:值为零的指针被称为空值指针,简称为空指针。
while(0)

1: char* k = NULL;
define NULL 0 //C的定义方式
define NULL (void *)0 //C++的定义方式
定义并初始化为NULL可以理解上面

2 char* k; 没有初始化指针也一定为0吗?
非常感谢大家热情讨论!谢谢!
kingstarer 2010-01-30
  • 打赏
  • 举报
回复
有时候可以不用,由调用函数方确保指针不为空

一般会在前面加上
assert(s!= NULL && t != NULL);

debug 版检查指针是否为空,如是则报错退出 release版为效率考虑不检查
successgl 2010-01-30
  • 打赏
  • 举报
回复
理论上是对的,后++总是先使用其原值,再++,这样的话,就是先判断原值s是否为\0了,但每个编译器不一定都这样实现吗?应该主流都这样实现吧,这方面不太懂
chary8088 2010-01-30
  • 打赏
  • 举报
回复
解释是对的
chary8088 2010-01-30
  • 打赏
  • 举报
回复
第一步(1)⑴ 会先判断 *t是否为空的
taoanran 2010-01-30
  • 打赏
  • 举报
回复
14楼正解,或者直接加一句*s='\0'代替*s = *t;
十八道胡同 2010-01-30
  • 打赏
  • 举报
回复
根据操作符的优先顺序来,

先赋值在判断
mstlq 2010-01-30
  • 打赏
  • 举报
回复
踏雪而歌的解释有问题

第二种解释才是对的……
先赋值,再判断
phpjspasp 2010-01-30
  • 打赏
  • 举报
回复
[Quote=引用楼主 kewenpan 的回复:]
引用:
===============================================================================================
yegaofei(踏雪而歌)  解释的不错!

  while(*s++=*t++);  在语义上等同于(注意条件部分是一个=,不是2个):

  while((*t)  !=  0){
          *s  =  *t;
          s++;
          t++;
  }

  显然前者更紧凑,效率(可能)更高。


arrowcy(长弓手)把流程解释得很清楚了
  我帮你再通俗说一遍:

  while(*s++=*t++);  这个在程序员杂志中,可能先声明了s和t都是字符串指针吧
  在执行的时候,实现了好几个逻辑,步骤如下:
  ⑴  *t  的赋值给  *s
  ⑵判断  *s  是否为真。如果为假,则跳出循环;否则继续执行第⑶步。因为字符串是以\0结尾的,遇到\0的时候,也就是*s为假,就跳出了字符串拷贝。
  ⑶  s  和  t  加  1,指向下一个地址,准备拷贝下一个字符。
==============================================================================================
有个问题 第一步(1)⑴  *t  的赋值给  *s  解释对吗?不用判断指针为空吗?
谢谢各位讨论
[/Quote]

while(*s++=*t++); 在语义上等同于(注意条件部分是一个=,不是2个):

while((*t) != 0){
*s = *t;
s++;
t++;
}
这两个不等同啊。
当*t == 0时,第一个会把*t赋给*s, 而第二个不会有这种效果。
  while(*s++=*t++); 语义等同于:

  while((*t) != 0){
*s = *t;
s++;
t++;
}
*s = *t; //新加的
某某寕 2010-01-30
  • 打赏
  • 举报
回复
学习了
发帖
C++ 语言

6.3w+

社区成员

C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
帖子事件
创建了帖子
2010-01-30 09:41
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下