编译环境为VS2005 编译为C文件。。。
首先看下下面这段:
int main()
{
char *name = "fengkewei";
char name1[] = "fengkewei";
char *name2 = "fengkewei";
char *name3 = "woaifengkewei";
int i = 10;
int j = 10;
int k = 11;
return 0;
}
若您觉得它们应该都保存在内存中的一块地方,那请往下看。。。。
下面是编译器为各个变量分配的内存地址,由于分配在栈上 所以地址是递减的
---------------------栈区------------------------------------
+ &name 0x0013ff5c unsigned char * *+
&name1 0x0013ff48 unsigned char [10]*
+ &name2 0x0013ff3c unsigned char * *
+ &name3 0x0013ff30 unsigned char * *
+ &i 0x0013ff24 int *
+ &j 0x0013ff18 int *
+ &k 0x0013ff0c int *
---------------------------------------------------------------
&name 和&name1[] 相差20个字节 但"fengkewei"只有10个字节(带空字符) &name1[]和&name2 相差12个字节后面都正常了 都差12 为什么是12?
————————————————————————————————————————————
下面是各字符串的首地址 它们都在文字常量区里 相同也就相同了 不同则是递增分配的( 文字常量区也是递增分配的)
---------------------------文字常量区-------------------------------------------------
+ name 0x004156b8 "fengkewei" unsigned char *
+ name2 0x004156b8 "fengkewei" unsigned char *
+ name3 0x00416010 "woaifengkewei" unsigned char *
+ name1 0x0013ff48 "fengkewei" unsigned char [10]
可见name1[]是在一个不同的地方的 也就是说它就是在栈上 现在我们设置一个整型指针 int *p; p = &i; 那p的地址应该是指向i的地址,指向栈区
果然:
+ &i 0x0013ff24 int *+ p 0x0013ff24 int *
--------------------------------------------------------------------
那当我设置一个字符型指针呢?
char *p;
p = name;
+ &name 0x0013ff5c unsigned char * *
+ name 0x004156b8 "fengkewei" unsigned char *
+ p 0x004156b8 "fengkewei" unsigned char * p
则指向的是字符串的地址,也就是指向文字常量区
------------------------------------------------------------------------------------------
为什么&name与name的地址不同呢?
因为name是个字符型变量,该变量的空间分配在栈区,name指向的字符串在文字常量区,而name又是个字符型指针变量,它里面所保存的值即为字符串在文字常量区的地址,这也就是为什么指针指向的内容和指针自身的地址不同的原因了。
可见 字符串常量是放在文字常量区的, 当你初始化赋值的时候 ,这些常量就先在文字常量区开辟一段空间,保存此常量。以后相同的常量就都在这里了。
还有
char name1[] = "fengkewei";
+ name1 0x0013ff48 "fengkewei" unsigned char [10]
- &name1 0x0013ff48 unsigned char [10]*
[0] 102 'f' unsigned char
[1] 101 'e' unsigned char
[2] 110 'n' unsigned char [
3] 103 'g' unsigned char
[4] 107 'k' unsigned char
[5] 101 'e' unsigned char
[6] 119 'w' unsigned char
[7] 101 'e' unsigned char
[8] 105 'i' unsigned char
[9] 0 unsigned char
可以看出 name1始终是指向一个地址的 这个地址 就是栈区的地址 这就可以理解为什么书上说name1就是表示数组的首地址了。但后面的101,102,103,...代表什么呢?是ASCII码。
看看文字常量区:
+ name 0x004156b8 "fengkewei" unsigned char *
name[0] 102 'f' unsigned char
name[1] 101 'e' unsigned char
name[2] 110 'n' unsigned char
也就是说不管在栈区还是在文字常量区,都是这样保存的。
但如果是这样呢:
char name4[20];
strcpy(name4, "fengkewei");
+ &name4 0x0013fee4 unsigned char [20]*
+ &name4[0] 0x0013fee4 "fengkewei" unsigned char *
+ &name4[1] 0x0013fee5 "engkewei" unsigned char *
+ &name4[2] 0x0013fee6 "ngkewei" unsigned char *
name4[0] 102 'f' unsigned char
name4[1] 101 'e' unsigned char
可见 每个数组元素的地址都在栈区 而它们的值保存的都是相应的字符。
也就是说 这个strcpy()并没有调用文字常量区的"fengkewei",而是直接把内容放在栈区name4[20]了.
同样
char name5[20] = "fengkewei";
+ name4 0x0013fee4 "fengkewei" unsigned char [20]
+ name5 0x0013fec8 "fengkewei" unsigned char [20]
可见 这两种方式是将"fengkewei"保存在栈区的.
最后总结下文字常量区的保存方式:
char *name = "fengkewei";
+ name 0x004156b8 "fengkewei" unsigned char * //name的值是保存在文字常量区"fengkewei"的地址
+ &name 0x0013ff5c unsigned char * * //name自身的地址则被编译器分配在栈区
name[0] 102 'f' unsigned char //name的第一个字符值为'f'
+ &name[0] 0x004156b8 "fengkewei" unsigned char * //它保存在文字常量区
name[1] 101 'e' unsigned char //第二个字符为'e'
+ &name[1] 0x004156b9 "engkewei" unsigned char * //它也保存在文字常量区
由此可见, 字符串常量, 按保存区域的不同分为以下几种:
一种是保存在栈区 , char name5[20] = "fengkewei"; 或 char name1[] = "fengkewei";
一种保存在文字常量区, 即 char *name = "fengkewei";
一种保存在全局区(静态区)
最后一种保存在堆区,即用malloc, alloc, realloc 分配内存分配的区域,可有程序员自身分配和释放
网上帖子很多 由于篇幅问题这里就不介绍了。。。
还有其他区:程序代码区 存放函数体的二进制代码。
当然了 看完这篇帖子 大家应该可以猜得到其他区的存储方式把....
文字常量在代码区 ,其中#define定义的常量也是在代码区
顺便说下文字常量和常变量的区别:
const char *name2 = "fengkewei";
const char *name2是常变量,fengkewei是文字常量,在代码区