char *p 与char p[] 比较

来源:互联网 发布:海洋污染危害数据事例 编辑:程序博客网 时间:2024/05/18 05:23

char *p 与char p[] 比较

所有的字符窜常量都被放在静态内存区
因为字符串常量很少需要修改,放在静态内存区会提高效率

例:

char str1[] = "abc";
char str2[] = "abc";

const char str3[] = "abc";
const char str4[] = "abc";

const char *str5 = "abc";
const char *str6 = "abc";

char *str7 = "abc";
char *str8 = "abc";


cout << ( str1 == str2 ) << endl;
cout << ( str3 == str4 ) << endl;
cout << ( str5 == str6 ) << endl;
cout << ( str7 == str8 ) << endl;

结果是:0 0 1 1
str1,str2,str3,str4是数组变量,它们有各自的内存空间;
而str5,str6,str7,str8是指针,它们指向相同的常量区域。

char *c = "chengxu"

"chengxu"的类型是const char *,编译器在编译时会在静态数据区为"chengxu"分配空间存储这个字符串,然后将字符串的首地址赋给字符指针char *c 。到于const char *赋给char *是因为在c语言时代这已成为一种习惯写法。所以,当使用指针c试图改变"chengxu"时,如:c[0]='a',编译不会出错,但运行时会出错。改成

char c[]="chengxu"就不会出错了。char c[]="chengxu"先在内存开辟一连续存储单元,然后将字符串存到存储单元。

函数中可以返回已经申请空间的局部变量的指针。

char *str()

{

   char *t ;

   t=(char*)maloc(50) ;

   return t ;

}

问题的引入:
看看下面的程序的输出:


#include <stdio.h>
char *returnStr()
{
    char *p="hello world!";
    return p;
}
int main()
{
    char *str=NULL;//一定要初始化,好习惯
     str=returnStr();
    printf("%s\n", str);
   
    return 0;
}
 

这个没有任何问题,因为"hello world!"是一个字符串常量,存放在静态数据区,
把该字符串常量存放的静态数据区的首地址赋值给了指针,
所以returnStr函数退出时,该该字符串常量所在内存不会被回收,故能够通过指针顺利无误的访问。

但是,下面的就有问题:
#include <stdio.h>
char *returnStr()
{
    char p[]="hello world!";
    return p;
}
int main()
{
    char *str=NULL;//一定要初始化,好习惯
     str=returnStr();
    printf("%s\n", str);
   
    return 0;
}

 
"hello world!"是一个字符串常量,存放在静态数据区,没错,
但是把一个字符串常量赋值给了一个局部变量(char []型数组),该局部变量存放在栈中,
这样就有两块内容一样的内存,也就是说“char p[]="hello world!";”这条语句让“hello world!”这个字符串在内存中有两份拷贝,一份在动态分配的栈中,另一份在静态存储区。这是与前者最本质的区别,
当returnStr函数退出时,栈要清空,局部变量的内存也被清空了,
所以这时的函数返回的是一个已被释放的内存地址,所以打印出来的是乱码。

如果函数的返回值非要是一个局部变量的地址,那么该局部变量一定要申明为static类型。如下:

#include <stdio.h>
char *returnStr()
{
    static char p[]="hello world!";
    return p;
}
int main()
{
    char *str=NULL;
     str=returnStr();
    printf("%s\n", str);
   
    return 0;
}
 

这个问题可以通过下面的一个例子来更好的说明:

#include <stdio.h>
//返回的是局部变量的地址,该地址位于动态数据区,栈里

char *s1()
{
    char* p1 = "qqq";//为了测试‘char p[]="Hello world!"’中的字符串在静态存储区是否也有一份拷贝
    char p[]="Hello world!";
    char* p2 = "w";//为了测试‘char p[]="Hello world!"’中的字符串在静态存储区是否也有一份拷贝
    printf("in s1 p=%p\n", p);
    printf("in s1 p1=%p\n", p1);
    printf("in s1: string's address: %p\n", &("Hello world!"));
    printf("in s1 p2=%p\n", p2);
    return p;
}

//返回的是字符串常量的地址,该地址位于静态数据区

char *s2()
{
    char *q="Hello world!";
    printf("in s2 q=%p\n", q);
    printf("in s2: string's address: %p\n", &("Hello world!"));
    return q;
}

//返回的是静态局部变量的地址,该地址位于静态数据区

char *s3()
{
    static char r[]="Hello world!";
    printf("in s3 r=%p\n", r);
    printf("in s3: string's address: %p\n", &("Hello world!"));
    return r;
}

int main()
{
    char *t1, *t2, *t3;
     t1=s1();
     t2=s2();
     t3=s3();
   
    printf("in main:");
    printf("p=%p, q=%p, r=%p\n", t1, t2, t3);

    printf("%s\n", t1);
    printf("%s\n", t2);
    printf("%s\n", t3);
   
    return 0;
}

 
运行输出结果:

in s1 p=0013FF0C
in s1 p1=00431084
in s1: string's address: 00431074
in s1 p2=00431070
in s2 q=00431074
in s2: string's address: 00431074
in s3 r=00434DC0
in s3: string's address: 00431074
in main:p=0013FF0C, q=00431074, r=00434DC0
$
Hello world!
Hello world!
 

这个结果正好应证了上面解释,同时,还可是得出一个结论:
字符串常量,之所以称之为常量,因为它可一看作是一个没有命名的字符串且为常量,存放在静态数据区。
这里说的静态数据区,是相对于堆、栈等动态数据区而言的。
静态数据区存放的是全局变量和静态变量,从这一点上来说,字符串常量又可以称之为一个无名的静态变量,
因为"Hello world!"这个字符串在函数 s1和s2 中都引用了,但在内存中却只有一份拷贝,这与静态变量性质相当神似。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 十一个月宝宝拉肚子拉水怎么办 小孩好动上课也坐不住会怎么办 幼儿大班关于环保的手抄报怎么办 捷达车打开丝位子风扇总转怎么办 小班个案分析:好动的孩子该怎么办 孩子突然过于的兴奋不睡觉是怎么办 刚出生的宝宝听力未通过怎么办 孩子多动症被老师打不上学怎么办 小孩在校被学生打家长该怎么办? 8岁儿童好动上课不注意听课怎么办 怀孕第一个月喝了啤酒怎么办 不知道自己怀孕喝了酒怎么办 怀孕一个月不知道喝酒了怎么办 老师说孩子上课不专心听讲怎么办 二年级孩子上课不认真听讲怎么办 二年级的孩子浮躁上课不认真怎么办 三年级的小孩上课不认真听讲怎么办 大班孩子上课不专心听讲玩怎么办 老师跟家长说小孩上课讲话怎么办 别的家长动手打自己的孩子怎么办? 一岁3个月宝宝骨龄偏小怎么办 宝宝9个月了越来越粘人怎么办? 孩子突然说话结巴口吃了怎么办啊 很久不说话了不敢说话了怎么办 宝宝2岁了还不会说话怎么办 2岁的宝宝还不会说话怎么办 小宝宝有四个月了母乳不够吃怎么办 一个月的宝宝吐奶厉害怎么办 新生儿吐奶吐一次吐的特别多怎么办 把孩子打了一次现在说话结巴怎么办 宝宝五岁了口吃越来越严重了怎么办 幼儿把自己的舌头扣破皮了怎么办 6岁宝贝烧到39度怎么办 2岁半的宝宝说话结巴怎么办 2周3宝宝不会说话胆小怎么办 宝宝我2岁多了说话有点结巴怎么办 两岁宝宝说话突然结巴了怎么办 两岁3宝宝叫她名字不理人怎么办 九个月的宝宝身高不达标怎么办 3岁宝宝又吐又拉怎么办 宝宝发烧39度怎么办手脚很烫