c语言中字符串常量到底存在于哪里?
常量存储总结
局部变量、静态局部变量、全局变量、全局静态变量、字符串常量和动态请求的内存空间
1、局部变量存储在堆栈中
2、全局变量、静态变量(全局和局部静态变量)存储在静态存储中
3、new申请的内存在堆里
4、字符串常数也存储在静态存储区
补充说明:
1、栈中的变量内存随定义区间的结束自动释放; 对于堆,必须手动自由。 否则,它会一直存在到程序结束。
2 .对于静态存储,其中的变量常数在程序运行过程中一直存在,不释放。 另外,变量常数其中只有一个副本,不会出现相同变量和常数的不同副本。
=====================================
以下文章清楚地介绍了字符串常量:
char *c='zhouming ';
在书中,字符串“zhouming”被视为常量,并位于此程序的内存静态区域中。
c是字符型指针,对于局部变量,它存储在堆栈中,而指针变量包含地址。
此地址是字符串中第一个字符z的地址。
使用printf (输出时,如果在格式化时选择%s,则输出zhouming。 这意味着当printf遇到终结符“ ”时将停止打印。
字符串“zhouming”是一个常量,存储在连续的内存中,末尾有终止符号,表示字符串的结束。
其一般int i=1;
所有字符文字都位于静态内存区域中
因为几乎不需要更改字符串常数,所以配置在静态内存区域可以提高效率
示例:
char str1[]='abcd ';
char str2[]='abcd ';
const char str3[]='abcd ';
const char str4[]='abcd ';
常数char * str5=' ABCD ';
常数char * str6=' ABCD ';
char *str7='abcd ';
char *str8='abcd ';
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是指针,指向相同的常数区域。“abcd”保存在静态数据区域,是全局的。
问题部署:
看看下面程序的输出:
#include stdio.h
char *returnStr ()
{
char *p='hello world!' ;
返回p;
}
int main () )
{
char *str=NULL; //请务必初始化,习惯
str=returnStr (;
printf(%s(n )、str );
返回0;
}
这没有任何问题。 ' hello world!' 是存储在静态数据区域中的字符串常量。
将存储该字符串常数的静态数据区域的起始地址分配给指针,
因而,在returnStr函数结束时,不回收该字符串常数所在的存储器,因此能够通过指针顺利地访问。
但是,存在以下问题。
#include stdio.h
char *returnStr ()
{
char p[]='hello world!' ;
返回p;
}
int main () )
{
char *str=NULL; //请务必初始化,习惯
str=returnStr (;
printf(%s(n )、str );
返回0;
}
'赫尔洛世界! "存储在静态数据区域中的字符串常数。 是的。
但是,字符串常量被分配给存储在堆栈中的局部变量(char [] )类型数组)。
这样就有两张内容相同的内存。 也就是说,“char p[]='hello world!' ”; ”这句话是“hello world! ”该字符串在内存中有两个副本,一个位于动态分配的堆栈中,另一个位于静态存储区中。 这是与前者最本质的区别,
当returnStr函数退出时,堆栈将为空,局部变量的内存也将为空
所以此时的函数返回的是
一个已被释放的内存地址,所以打印出来的是乱码。如果函数的返回值非要是一个局部变量的地址,那么该局部变量一定要申明为static类型。如下:
static 主要是为了限定范围用的。
#include <stdio.h>
char *returnStr()
{
static char p[]="hello world!";
return p;
}
int main()
{
char *str=NULL;
str=returnStr();
printf("%sn", 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=%pn", p);
printf("in s1 p1=%pn", p1);
printf("in s1: string's address: %pn", &("Hello world!"));
printf("in s1 p2=%pn", p2);
return p;
}
//返回的是字符串常量的地址,该地址位于静态数据区
char *s2()
{
char *q="Hello world!";
printf("in s2 q=%pn", q);
printf("in s2: string's address: %pn", &("Hello world!"));
return q;
}
//返回的是静态局部变量的地址,该地址位于静态数据区
char *s3()
{
static char r[]="Hello world!";
printf("in s3 r=%pn", r);
printf("in s3: string's address: %pn", &("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=%pn", t1, t2, t3);
printf("%sn", t1);
printf("%sn", t2);
printf("%sn", 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 中都引用了,但在内存中却只有一份拷贝,这与静态变量性质相当神似。
另外还有个实验:
[cpp]
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
char *b;
char *c;
char a[]="chenhuijie";
b="chenhuijie";
c="chenhuijie";
printf("%d,%d,%d,%dn",b,a,c,&("chenhuijie"));
}
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
char *b;
char *c;
char a[]="chenhuijie";
b="chenhuijie";
c="chenhuijie";
printf("%d,%d,%d,%dn",b,a,c,&("chenhuijie"));
}
实验结果为:
4282272,1244988,4282272,4282272
请按任意键继续. . .
对了,字符常量‘a’
sizeof(‘a’)
为4,及一个字长。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct _http_str
{
char *p;
int len;
//for internal use only, field MUST be of integer type
int trait; //won't enlarge struct due to gcc's default alignment
} http_str_t;
int aa;
http_str_t * get_info()
{
static http_str_t s = { " ", 0, 0 };
int a;
char b[] = "abc";
printf("s.p:%p, string addr:%pn", s.p, &(" "));
printf("b:%p, string addr:%pn", b, &("abc"));
s.p = b;
printf("s:%p, s->p:%p, a:%p, aa:%p, b:%pn", &s, s.p, &a, &aa, b);
return &s;
}
int main()
{
http_str_t *s = get_info();
printf("p=%pn", s->p);
printf("*p=%sn", (s->p));
printf("sizeof('a'):%lu, %lu, sizeof(5):%lu, sizeof(&"a"):%lun", sizeof('a'), sizeof("a"), sizeof(5), sizeof(&("a")));
return 0;
}