关于字符串常量在内存中的生命周期

字符串char *s="hello"; 与char s[]="hello";,看似都是将hello字符串的地址赋值给指针 *p。

但是前面一个表达式是字符串常量的地址赋值给指针 该指针指向的字符串中的字符是不允许被更改的。

而后面一个表达式是将该字符串的每一个字符赋值给数组,该指针指向的数组的首地址,而数组成员是变量,因此可以允许被更改赋值。

关于以上个问题我们就不做详细讨论了,网上有很多文章关于这个问题的。主要讨论由以上这个问题引出来的关于字符串常量在内存中存在生命周期的的问题。

问题如下:

假如 char *s0="hello";

s0="world";

就是说如果开始s0指针指向“hello”这个字符串这个常量的地址,但是当s0指针指向了“world”符串的时候那么“hello”这个字符串在内存中的是否会被释放掉,还是会一直存在内存中,直到程序结束。

我们不妨先试着写几行代码,通过运行结果来进行分析:

案例 一:

代码:

#include<stdio.h>
int main()
{
char *s0,*s1,*s2;
s0="hello";
s1="hello";
s2="hello";
printf("%0x\n",s0);
printf("%0x\n",s1);
printf("%0x\n",s2);
return 0;
}
运行结果:

三个指针变量的指向的地址都是相同的,如图




分析:

通过运行结果我们可以看出,赋给不同字符指针的相同的字符串,所有的指针都指向了相同的地址。

但是案例一由于三个指针变量都在同一个函数,因此不能看出其生命周期,但是可以为下面的案例解释做好铺垫。

案例二:

代码:

#include<stdio.h>
char *s0="hello";
void a()
{
char *s1="hello";
printf("%0x\n",s1);
s1="world";
}
void b()
{
char *s2="hello";
printf("%0x\n",s2);
s2="world";
}
int main()
{
char *s3=(char *)0;
printf("%0x\n",s0);
a();
b();
s3="hello";
printf("%0x\n",s3);
return 0;
}

运行结果:



四个字符指针变量指向的地址还是一样的。


分析:这就说明问题了,在函数a(),b()中,局部指针变量*s1,*s2都指向”hello“字符串,但是在退出之前有改变指针指向其他字符串,但是两个字符串指针打印出来的地址还是一样的,说明在使用了字符串常量后,该字符串常量并没有在随着函数的结束而消失,而是依旧存在于内存中,因此当其他函数中使用一样的字符串常量时,指向的依旧是跟还是一样的地址。但是也许有人会问到,因为有在全局字符指针变量 char *s0 ="hello";指向了该字符串常量,会像全局变量一样,在真个程序运行都不会释放,因此其他函数调使用该字符串常量时才指向了同一地址。确实确实有这种可能,那么我们就可以看下面案例三。

案例三:

#include<stdio.h>
void a()
{
char *s1="hello";
printf("%0x\n",s1);
s1="world";
}
void b()
{
char *s2="hello";
printf("%0x\n",s2);
s2="world";
}
int main()
{
char *s3=(char *)0;
a();
b();
s3="hello";
printf("%0x\n",s3);
return 0;
}

运行结果:



三个字符串指针变量指向的地址还是一样的,如图


分析:

当我们去掉全局指针变量后,其结果依旧是*s1,*s2,*s3 三个指针变量指向的地址依旧是没有变。在运行完a(),b()两个函数之后,我们再将”“hello”赋值给空指针*s3指针,其指向地址与*s1,*s2都一样的。因此我们可以得出结论:一旦有字符串常量在运行期间创建,就会在内存中一直保持到程序结束,当使用相同的字符串常量的时候,不会再创建字符串常量,而是指向之前的那个。因此字符串常量是贯穿整个程序的生命周期的。



以上代码在GCC VC上都进行过编译运行,其结果都一致。

这是本人在csdn的第一篇博客,发博也是为了与大家沟通交流,向前辈们学习。之前没有在怎么用过发过类似的东西,因此在写的过程中,语言的组织之类,以及在验证方法的可能会有不科学之处,希望大家指正。我现在还是菜鸟,但是我会一直坚持下去,坚持将自己的看书,学习,项目的经验心得与大家分享,也希望大家批评指正讨论交流。


附:既然说到这里了,那就再多说一点

案例:当将 char *s0 改为char s0[ ]时

代码:

#include<stdio.h>
char s0[]="hello";
void a()
{
char *s1="hello";
printf("%0x\n",s1);
s1="world";
}
void b()
{
char *s2="hello";
printf("%0x\n",s2);
s2="world";
}
int main()
{
char *s3=(char *)0;
printf("%0x\n",s0);
a();
b();
s3="hello";
printf("%0x\n",s3);
return 0;
}

运行结果:



s0与s1 、s2、 s3指向的地址不同


分析:造成这样的结果的原因是因为char s0[]="hello",而*s0指向的是该数组的首地址,而不是字符串的首地址。而*s1、 *s2、 *s3都是指向字符串的首地址,因此不同。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值