关于c语言中字符串和指针的一点困惑,求指教!

呀二呀 2015-08-26 03:54:55
有这么一道题目,大家先看看

#include <stdio.h>
int main()
{
char notes[]="See you at the snack bar.";
char * ptr;

ptr=notes;
puts(++ptr);
notes[7]='\0';
puts(++ptr);

return 0;
}


参考答案是:e you
我的答案是:e you at the snack bar
我的想法是这样:先把字符串首地址赋值给ptr,那么经过两次ptr自增后输出的应该是e you at the snack bar.
中间的那条语句note[7]='\0'仅仅是改变了字符数组的内容,但没有改变内存中的字符串的内容。
我强调这两点,是因为我认为程序执行后,数据区的字符串会被赋值给字符数组notes,notes[7]='\0'只是改变了
数组的,而对原本的字符串内容未作更改。不知道这样错在哪里,请大牛指教!
...全文
390 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
苏叔叔 2015-09-10
  • 打赏
  • 举报
回复
引用 21 楼 zhao4zhong1 的回复:
[quote=引用 20 楼 zhangxiangDavaid 的回复:] 眼见为实:

#include <stdio.h>
int main()
{
	char notes[] = "See you at the snack bar.";
	char * ptr;

	ptr = notes;
	puts(++ptr);
	notes[7] = '\0';
	puts(++ptr);

	return 0;
}
//ee you at the snack bar.
//e you
些微侵犯了zhao4zhong1的将代码运行结果作为注释放在代码尾部的专利(还没申请)![/quote] 我已经提前申请了。 zhangxiang:这是你的专利。 zhao4zhong1:不,这是你的专利!
赵4老师 2015-09-10
  • 打赏
  • 举报
回复
引用 20 楼 zhangxiangDavaid 的回复:
眼见为实:

#include <stdio.h>
int main()
{
	char notes[] = "See you at the snack bar.";
	char * ptr;

	ptr = notes;
	puts(++ptr);
	notes[7] = '\0';
	puts(++ptr);

	return 0;
}
//ee you at the snack bar.
//e you
些微侵犯了zhao4zhong1的将代码运行结果作为注释放在代码尾部的专利(还没申请)!
苏叔叔 2015-09-10
  • 打赏
  • 举报
回复
眼见为实:

#include <stdio.h>
int main()
{
	char notes[] = "See you at the snack bar.";
	char * ptr;

	ptr = notes;
	puts(++ptr);
	notes[7] = '\0';
	puts(++ptr);

	return 0;
}
//ee you at the snack bar.
//e you
lkjasdf9909 2015-09-09
  • 打赏
  • 举报
回复
notes[7]='\0'; 表示7这个位置是字符串的结束位置 puts(++ptr) 就会输出e到u这个几个字符
均陵鼠侠 2015-09-08
  • 打赏
  • 举报
回复
这个问题,可以分步骤解释如下:
char notes[]="See you at the snack bar.";
这一句,字面串"See you at the snack bar."在程序转换阶段先是在末尾添加一个空字符'\0',然后用于初始化一个不可见的静态数组。最后,C的实现用这个数组的内容初始化数组notes。
char * ptr;
ptr = notes;
这两句,数组notes自动转换为指向其第一个元素的指针,并将这个指针赋给ptr。也就是说,ptr现在指向数组notes的首元素,也就是notes [0]。
puts(++ptr);
这一句,puts函数要求一个字符串。字符串是一个字符的序列,且以第一个遇到的空字符('\0')终止。字符串包括单字节字符的序列和多字节字符的序列,但应与宽字符的序列相区别。 不管怎么说,因为在传递给puts函数之前,表达式++ptr的效果是指向数组notes的第二个元素(notes [1]),所以输出的是 ee you at the snack bar.
notes[7]='\0';
这一句,将数组的7号元素修改为空字符'\0'。此时,数组notes的元素是 See you\0at the snack bar.
puts(++ptr);
这一句,在进入puts函数之前,表达式++ptr的效果是指向数组notes的第三个元素(notes [2]),我们知道,puts函数输出一个字符串,但是,因为前面已经在数组中加入一个空字符'\0',所以它指向的串,以入puts函数的输出实际上是 e you 以上的关键是搞清楚数组、指针和字符串这几个概念。再来看另一个例子:
char keywords [] = "if\0else\0switch\0while";
这是一个数组,从字符串的角度来看,它包含了4个字符串,可以这样输出它们:
puts (keywords);
puts (keywords + 3);
puts (keywords + 8);
puts (keywords + 15);
赵4老师 2015-09-08
  • 打赏
  • 举报
回复
理解讨论之前请先学会如何观察! 计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构…… 对学习编程者的忠告: 多用小脑和手,少用大脑、眼睛和嘴,会更快地学会编程! 眼过千遍不如手过一遍! 书看千行不如手敲一行! 手敲千行不如单步一行! 单步源代码千行不如单步Debug版对应汇编一行! 单步Debug版对应汇编千行不如单步Release版对应汇编一行! VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。 对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。 (Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。) 电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址; 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……
janneliu 2015-09-08
  • 打赏
  • 举报
回复
将指针传给puts()函数,而该指针也指向数组的首地址,因此修改的是同一块区域,楼主想的是两个不同地方是错误的
heishu007 2015-09-01
  • 打赏
  • 举报
回复
一个字符串的结束是\0,所以只要遇到\0该字符串就算结束
pricks 2015-09-01
  • 打赏
  • 举报
回复
看看编译后的
lm_whales 2015-08-30
  • 打赏
  • 举报
回复
改掉''\0' 不是多一位(字节),而是多了不确定位(字节), 字符串长度,超过字符数组长度(超过数组定义的空间范围) puts 的时候,属于越界读。 这本来就是错误,用它来确定字符串长度是不对的 另外,C语言 数组越界,是可以操作的, 不是C语言层面上的错误。 只是程序逻辑错误。 C语言是不保证这种代码安全的。。。 一般来说,编译器不检查这种错误, 不过很多编译器,生成调试版本程序的时候, 可以一定程度的检测到这种错误。 聪明一点的编译器,也可能对某些错误,给出一些警告。 但这些都是不可靠的。关键还要自己掌握
lm_whales 2015-08-30
  • 打赏
  • 举报
回复
"See you at"共十个字符, C语言给他加个'\0' , 共十一个字符。 对于用字符串字面值, 初始化的字符数组(未定义数组元素个数)来说, 字面值的字节数,就是数组的元素个数。 字符串字面值,约定就是串内字符,所占字节,加上'\0' 所占字节。 第十一个字符恰恰就是 notes[10] ,第一个是notes[0] 你给改为 ‘a’ 以后,这个字符数组,就不在成为字符串了 但是puts函数是字符串输出函数,约定包含 '\0' 的, puts(ptr); 没有找到‘\0' 他会继续找,找到之前的字符都会输出 至于这个'\0' 啥时候会出现,不确定, 不过一般来说,不论如何总能找到的, 程序空间不可能,一个字节为0值的内存,也没有。 除非最终找到某个不可读位置,程序报错, 程序总会输出些什么的。 但这是不可控的,输出的内容不是你希望输出的。
qq_30446977 2015-08-29
  • 打赏
  • 举报
回复
引用 9 楼 lm_whales 的回复:
字符串,C语言中用字符数组表示(实现)。 只是字符串以 ‘\0’ 结束, 此后的字符,都不属于字符串了,字符串,不是C语言的数据类型。 字符数组,定义了多少元素,就有多少字节,就有多少个字符,是一个集合类型。 不管 ‘\0’ 在哪里,字符数组的元素数,都是定义时候的个数。 字符串的长度,随着‘\0’的位置而变化。 一个没有‘\0’的字符数组,不是一个字符串。 字符串字面值(串常量),实现上也是字符数组这一类的东西。 字符串,是C 语言不明确定义的数据类型,这个类型 不属于C语言。但是约定这么用,这么实现。
说的很对啊。都是很基本的东西。但是很有用的。借用的继续往下深究。如果没有\0,会出现什么情况: #include <stdio.h> int main() { char notes[]="See you at"; char * ptr; ptr=notes; notes[10]='a'; puts(ptr); return 0; } 运行结果是:See you ata誑。数组不是11位吗(编译器自动给加了个\0),为什么改了\0,会多出一位。??
lin5161678 2015-08-29
  • 打赏
  • 举报
回复
你想法错误 其实是 先把数组首元素地址赋值给ptr
lm_whales 2015-08-29
  • 打赏
  • 举报
回复
字符串,C语言中用字符数组表示(实现)。 只是字符串以 ‘\0’ 结束, 此后的字符,都不属于字符串了,字符串,不是C语言的数据类型。 字符数组,定义了多少元素,就有多少字节,就有多少个字符,是一个集合类型。 不管 ‘\0’ 在哪里,字符数组的元素数,都是定义时候的个数。 字符串的长度,随着‘\0’的位置而变化。 一个没有‘\0’的字符数组,不是一个字符串。 字符串字面值(串常量),实现上也是字符数组这一类的东西。 字符串,是C 语言不明确定义的数据类型,这个类型 不属于C语言。但是约定这么用,这么实现。
hzup111 2015-08-27
  • 打赏
  • 举报
回复
字符串和字符数组不是同一个东西吧,他们存储的地方不一样
  • 打赏
  • 举报
回复
最开始ptr执行的地址应该S所在的地址,第一个puts的输出应该是:ee you at the snack bar. 而此时ptr所指向的地址应该是第一个e所在的地址,但是notes指向的地址还是S所在的地址,notes[7]='\0';会将you后面的空格编程'\0'(字符串结束符),第二puts输出时,是先将ptr的地址指向第二个e,然后再puts,所以是:e you
707wk 2015-08-26
  • 打赏
  • 举报
回复
都是同一个字符串
呀二呀 2015-08-26
  • 打赏
  • 举报
回复
引用 1 楼 zhao4zhong1 的回复:
不要迷信书、考题、老师、回帖; 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实! 有人说一套做一套,你相信他说的还是相信他做的? 其实严格来说这个世界上古往今来所有人都是说一套做一套,不是吗?
您说的很对,只有机器是说一不二的
「已注销」 2015-08-26
  • 打赏
  • 举报
回复
该字符串最后被修改为: See you\0at the snack bar. 即第二个字符被清零。然而指针指向的是第三个字符 e,所以输出: e you
「已注销」 2015-08-26
  • 打赏
  • 举报
回复
你口中的字符串和字符数组其实是同一个东西,不存在改变哪个没改变哪个的。
加载更多回复(2)

69,374

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧