参考资料: 数据结构中的栈。 结构中的堆是两回事,分配方式倒是类似于链表,呵呵。 变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统 释放。
字符数组和字符串指针的区别 char a[] = "Hello World"; char *p = "Hello World"; *(a+1) =u; *(p+1) =u; *(a+1) =u;操作会通过,而*(p+1) =u;操作则会出现段错误。这是什么原因呢?那么我们需要了解下,程 序空间分配中存储区问题。C/C++程序所对应的存储区,分位三类: 1.)静态存储区:内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。它主要存 放静态数据、全局数据和常量。 2.)栈区:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自 动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。 3.)堆区:亦称动态内存分配。程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责在适 当的时候用free或delete释放内存。 这里char a[] = "Hello World",其空间是分配在栈中的,所以你可以对其中的内容进行修改。而char *p = “Hello World”,其空间是分配在静态存储区的。且Hello world为字符串常量,是不允许修改
在x.c中定义了一个字符数组 char s[100],
在l.c中进行引用extern char s[200], 有些c程序新手经常把它写成extern char *s。 这两种写法的含义一样吗? 首先得理解声明与定义的含义: 定义一个变量意味着要给它进行内存分配, 而声明一个变量则可以在其他文件中, 只是进行一种声明, 表示有这个变量存在, 但是在其他文件中定义, 声明后不用分配内存。 我们看一下extern char s[100]与extern char *s在执行s[10]的取值过程是什么样的: 1、 extern char s[100], s是个符号, 它既是一个数组的名称, 又是数组的起始地址, 假设编译器在编译的时候给s分配的地址是6789, 那么程序在执行s[10]的时候, 先找到s符号的地址6789, 然后在取(6789+10)地址上的内容。 2、extern char *s它声明了s是个指针, 既然是指针, 那么取址的过程就是间接的。 s这个符号在编译的时候也是有地址的, 不过这个地址上的内容又是一个地址, 在这个地址上保存的才是要存取的内容。当在x.c中定义s为字符数组后, 在l.c中声明s却是个指针, 这样在用s[10]操纵的时候会出现什么问题呢? s在x.c中被编译器分配的地址是6789, 在l.c中被当成指针了, 所以先找到6789这个地址, 在这个地址上取值作为内容的地址,6789上实际保存的是s[0]的值, 我们假设为'a', 然后程序会把'a'这个值当成地址, 然后去'a'这个地址上取内存内容, 'a'地址上显然存放的是内核数据段或代码段, 应用程序显然会报错的。 如果s[0]存放的即使是应用层程序可以访问的内容, 那么程序也会出现莫名其妙的bug。 所以c程序员一定要搞清数组和指针并不是完全相同的。 |