char* p与char p[]

C++内存的5个区:

(⊙v⊙)嗯,其实这5个区没啥好说的。但是为了之后要写的内容,先把这5个区简单说一下嘛。

:就是那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区。里面的变量通常是局部变量、函数参数等。

:就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。

自由存储区:就是那些由malloc等分配的内存块,与和堆是十分相似的,不过它是用free来结束自己的生命的。

全局/静态存储区:全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区

常量存储区:这是一块比较特殊的存储区,他们里面存放的是常量,一般是不允许修改的。

栈与堆

感谢

http://blog.chinaunix.net/uid-14825809-id-301187.html

对于堆,我们首先要知道操作系统有一个记录空闲内存地址的链表。当系统收到程序的需要分配内存的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆节点,然后把该节点从空闲节点链表中删除,并将该节点的空间分配下去。另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样代码中的delete语句才能正确的释放本内存空间。还有,由于找到的堆节点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲的链表中。所以频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片。

对于申请大小的限制。栈在windows下,栈是向低地址扩展的数据结构,是一块连续的内存区域。也就是说栈顶的地址和栈的最大容量是系统预先规定好的(好像VS上面是1M样),如果申请的空间超过栈的剩余空间,将会提示overflow。而对于堆来说,堆是向高地址扩展的数据结构,是不连续的内存区域。我们之前说过我们是通过空闲内存地址的链表的帮助来分配内存的,所以自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。

还有,在函数调用时,第一个进栈的是主函数中函数调用语句的下一条指令的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右到左入栈,然后是函数中的局部变量。注意静态变量是不入栈的。当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数的下一条指令,程序由该点继续运行。

有趣的小例子

int main(){
  char* p="hello1";
  char a[]="hello2";
  p[2]='A';
  a[2]='A';
  return 0;
}

这个代码是有错的,p[2]=’A’错了。指针变量p和变量数组a都在栈区,”hello1”与”hello2”都是字符串常量在常量存储区,不过字符串常量”hello2”赋值给了一个局部变量(char []型数组)。字符串常量”hello2”在内存就有两份拷贝了,一个在动态分配的栈中,一个在常量存储区中。p[2]=’A’是对常量存储区中的字符串”hello1”进行修改,这肯定是不行的,而a[2]=’A’就可以了,它是对栈中的char型数组a进行修改。

再来一个例子

int main(){
   char* p="hello1";
   char a[]="hello2";
   p++;
   a++;
   return 0;
}

这个代码也是有错的。a++错了,a是一个数组名,相当于一个常量指针不能被修改。
我们再次强调一下:
p是指向字符串常量首地址的指针,内容为常量不可修改,指针可以修改;
a是指向数组的常量指针,指针不可修改,内容可修改。

再来一个例子

char *returnStr1()
{
    char *p="hello1";
    return p;
}
char *returnStr2()
{
    char p[]="hello2";
    return p;
}
int main()
{
    char *str1=NULL;
    str1=returnStr1();
    printf("%s\n", str1);

    char *str2=NULL;
    str2=returnStr2();
    printf("%s\n", str2);

    return 0;
}

“hello1”是字符串常量,被放在常量存储区,把该字符串常量存放在常量存储区的首地址赋给指针p,当returnStr1函数结束退出后,该字符串常量所在的内存不会被回收。而对于returnStr2函数中的局部变量char型数组p中存放的是字符串常量”hello2”赋值给的,这个是在动态分配的栈中,当returnStr2函数结束退出后,局部变量的内存被回收,这时候返回的地址是已经被释放的内存地址了。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值