标题:字符串指针问题
只看楼主
有容就大
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:东土大唐
等 级:版主
威 望:74
帖 子:9048
专家分:14309
注 册:2011-11-11
得分:0 
回复 9楼 TonyDeng
你这么一说我就明白了。也就是说在数组初始化时比如 char s1[100] = "*****"; 是分配了100可以改变值的变量存储位置。而 char *s1 = "*****"; 是分配了一段不可改变值的常量区,并把首地址送给这个指针。
如果我上面理解的没错,那么 char *s1;这个指针貌似没多大的作用,反而乱用会影响程序的功能?

梅尚程荀
马谭杨奚







                                                       
2012-01-03 14:58
有容就大
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:东土大唐
等 级:版主
威 望:74
帖 子:9048
专家分:14309
注 册:2011-11-11
得分:0 
回复 10楼 TonyDeng
数据被强奸? 嘎嘎

梅尚程荀
马谭杨奚







                                                       
2012-01-03 14:59
embed_xuel
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:58
帖 子:3845
专家分:11385
注 册:2011-9-13
得分:3 
回复 11楼 有容就大
"hello word!\n"是字符串常量,存在常量区,char *pmessage = "hello word!\n";定义了一个指针变量指向常量区的字符串常量,char amessage[] = "hello word!\n";定义了一个字符数组,局部变量,在栈上,并拷贝了一份放在数组里,所以用指针是改变常量区,是错误的,用数组改变的是栈上的。

总有那身价贱的人给作业贴回复完整的代码
2012-01-03 15:00
有容就大
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:东土大唐
等 级:版主
威 望:74
帖 子:9048
专家分:14309
注 册:2011-11-11
得分:0 
回复 13楼 embed_xuel
嗯 现在懂点了。 你说的和5楼解释的一样,不过当时没懂静态常量区的具体含义。

梅尚程荀
马谭杨奚







                                                       
2012-01-03 15:03
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
得分:0 
分两截看:

char s1[100];
是分配100char的空间,命名为s1,s1也作为入口地址。

"*****"
是6char的字符常量,只读的。

那么
char s1[100] = "*****";
是把"*****"常量数据抄写到s1中去。注意:是“抄写”,不是什么指针赋值。抄完之后各归各。你可以随意修改s1中的数据,但无法修改"*****"中的任何数据。

char *p;
仅仅是声明一个指针,它不是什么数组的入口地址。也就是说,这种指针是“自由指针”,而s1是非自由的,它总是那块空间的入口地址,无法递增,但p可以。

[ 本帖最后由 TonyDeng 于 2012-1-3 15:12 编辑 ]

授人以渔,不授人以鱼。
2012-01-03 15:04
有容就大
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:东土大唐
等 级:版主
威 望:74
帖 子:9048
专家分:14309
注 册:2011-11-11
得分:0 
回复 15楼 TonyDeng
谢谢你说的这么清晰!

不过我还有点问题。
char s1[100] = "*****";
是把"*****"常量数据抄写到s1中去。注意:是“抄写”,不是什么指针赋值。抄完之后各归各。
1.按这样说 char s1[100] = "******";一个语句是不是就在内存里划分了两个存储区?
2.按常理指针都是到处指啊指的,那么一个不自由的指针即指针常量他的用处是什么,是不是程序中应当尽量避免它出现?

梅尚程荀
马谭杨奚







                                                       
2012-01-03 15:18
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
得分:0 
确实是两块不同的数据区域,这跟编译原理有关。"*****"这样的叫硬编码,比如常量123、#define PI 3.14后的PI也是,因为这些数据在程序中被写死了,编译器首先要为这些数据寻求存身之地,就要开辟空间给它们寄存,而又因为那是硬编码死数据,编译器自然有充分的理由认为那是不需要修改的,而只读的数据在运行处理时效率最高,因此优先把这类数据放在只读数据区。

s1[100]这样的声明,只有空间说明而无内容说明,很明显是后期需要填写、修改数据的,就无法放在只读区了,这种数据空间尺寸是常数,一般有限,为着效率起见,它们可以放在栈式空间中,除了尺寸无法改变,数据是可以擦写的,这个存储区擦写的速度很快。一般参数传递,需要反复写入和废弃数据,就利用这块存储区。这个区域本身是有限的,数据多了,剩余就少,因此不适宜放置长期赖死不走的数据。你在函数中用局部变量声明s1[100],它会在函数结束后被收回,就是这个道理。

对尺寸再大的数据,或者需要赖相当长时间的数据,就可以考虑在堆空间中存储。这个空间效率是最低的,但却胜在无节制。malloc()就是在这里申请存储空间,这个时候,编译器无法确认你什么时候才应该释放它,那么它干脆不做,留给你自己做,你不释放,它就一直占着,直到被操作系统强制收回。小程序影响不大,对内存紧张的机器(如手机之类),你这样霸占空间的后果就是大家(包括自己)都可能没有空间可用了。想象一下,在1G的磁盘中,你在磁盘中间占用了500M,理论上还有500M剩余,但事实上由于你占用的是中间区域,那么两侧剩下的都没有500M,要再申请500M空间,那是不可能,甚至连250M都拿不到。道理就是这样。

数组需要记忆入口地址,自由指针离开了入口,它无法记得入口地址在哪里,需要循原路返回,也就是说,你得另外分配一个变量记忆路径(比如p=s1, p+=i之后,就得靠i返回入口处,否则它就失根了),数组的名字,虽然可以“视为”指针,但它其实不是真正的指针,它只是一个入口地址罢了。数组名字转变为指针的时候,是它作为实参被值传送到函数中的时候,比如func(char *s)这样的函数,如果调用处是func(s1),那么到了func()中,s就成了自由指针。

授人以渔,不授人以鱼。
2012-01-03 15:44
edward_eric
Rank: 2
等 级:论坛游民
帖 子:32
专家分:83
注 册:2011-10-5
得分:2 
一开始就错了,在声明字符指针变量的时候才可以直接把字符串常量赋值给字符指针,但是不允许在非变量声明的时候进行这样的操作。而且,这些字符串常量都是存在只读区域里面的,不能改变。
2012-01-03 15:54
有容就大
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:东土大唐
等 级:版主
威 望:74
帖 子:9048
专家分:14309
注 册:2011-11-11
得分:0 
回复 17楼 TonyDeng
非常感谢你的讲解.

梅尚程荀
马谭杨奚







                                                       
2012-01-03 17:19
有容就大
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:东土大唐
等 级:版主
威 望:74
帖 子:9048
专家分:14309
注 册:2011-11-11
得分:0 
谢谢大家这么热心,

梅尚程荀
马谭杨奚







                                                       
2012-01-03 17:19



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-359061-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.336553 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved