C++内存分配及字符串赋值

 本文介绍在Ubuntu12.10g++环境下C++内存分配问题。并由此解释在用g++编译时,字符串常量赋值给字符指针类型时提示warningdeprecated conversion from string constant to 'char *'警告的原因

一、C++内存分配

\
 

       C++编译器将应用程序的内存空间分成四个部分,从内存低地址开始依次为:代码和常量区(用于存储只读的代码数据和常量值)、全局变量和静态变量区(用于存储全局变量和静态变量)、堆区(用于保存newmalloc申请的内存)、栈区(用于保存函数返回地址、局部变量等)。

我们将用如下代码来测试我们的假设:


01. #include <iostream>
02. #include <stdio.h>
03. #include <string.h>
04. #include <malloc.h>
05.  
06. using namespace std;
07.  
08. int quanju;/*全局变量,全局区/静态区(static)*/
09. void fun(int f_jubu); /*代码区*/
10. int main(void)
11. {
12. int m_jubu;/*栈区(stack)*/
13. static int m_jingtai;/*静态变量,全局区/静态区(static)*/
14. const int conInt = 5;/*main中的局部变量,位于栈区,被const修饰,变量值不可变*/
15. static const int sconInt = 6;/*常量,位于常量区*/
16. char *m_zifum,*m_zifuc = "hello";/*指针本身位于栈。指向字符串"hello",位于代码区/常量区*/
17. char* zifuc_hw = "hello world";/*字符串"hello world",位于常量区*/   
18.  
19. /*正确的赋值方式*/
20. char *zif = (char*)malloc(sizeof(char) * 6);
21. strcpy(zif, "hello");
22. cout<<zif<<endl;
23. cout<<m_zifuc<<endl;
24.  
25. void (*pfun)(int); /*栈区(stack)*/
26. int (*pmain)(void);
27. pfun=&fun;
28. pmain = &main;
29. m_zifum = (char *)malloc(sizeof(char)*10);/*指针内容指向分配空间,位于堆区(heap)*/
30. pfun(1);
31. cout<<"全局变量        :"<<&quanju<<endl;
32. cout<<"main静态变量        :"<<&m_jingtai<<endl;
33. cout<<"main字符串常量(hello)    :"<<(void*)m_zifuc<<endl;
34. cout<<"main字符串常量(h w)  :"<<(void*)zifuc_hw<<endl;
35. cout<<"main局部变量(const修饰):"<<&conInt<<endl;
36. cout<<"main静态整型常量  :"<<&sconInt<<endl;
37. cout<<"fun函数代码地址       :"<<(void*)pfun<<endl;
38. cout<<"main函数代码地址  :"<<(void*)pmain<<endl;
39. cout<<"main字符串(堆分配)    :"<<(void*)m_zifum<<endl;
40. cout<<"main函数函数指针变量    :"<<&pfun<<endl;
41. cout<<"main局部变量        :"<<&m_jubu<<endl;
42. cout<<"main局部变量        :"<<&m_zifuc<<endl;
43. cout<<"main局部变量        :"<<&m_zifum<<endl;
44. return 0;
45. }
46. void fun(int f_jubu)
47. {
48. static int f_jingtai;
49. char* f_zifuc = "hello";
50. cout<<"fun静态变量     :"<<&f_jingtai<<endl;/*静态变量,位于静态区*/
51. cout<<"fun字符串常量(hello) :"<<(void*)f_zifuc<<endl;/*常量,位于常量区,同main中的“hello”地址相同*/
52. cout<<"fun形参变量     :"<<&f_jubu<<endl;/*栈区(stack),但是与主函数中m_jubu位于不同的栈*/
53. cout<<"fun局部变量     :"<<&f_zifuc<<endl;
54. }

实验结果:

hello

fun字符串常量(hello :     0x8048c58

main字符串常量(hello :  0x8048c58

main字符串常量(hw :     0x8048c5e

main静态整型常量 :         0x8048e64

main函数代码地址 :         0x80487dc

fun函数代码地址 :           0x8048a73

fun静态变量 :                 0x804a0f8

main静态变量 :               0x804a0fc

全局变量 :                      0x804a0f0

main字符串(堆分配) :     0x9ed0008

fun形参变量 :                 0xbfe0e8b0

fun局部变量 :                 0xbfe0e89c

main函数函数指针变量 : 0xbfe0e8d4

main局部变量 :              0xbfe0e8c8

main局部变量 :              0xbfe0e8d0

main局部变量 :              0xbfe0e8cc

main局部变量(const修饰) :0xbfe879d8

二、堆区和栈区的比较

       两个区的主要区别在于以下几个方面:

1、管理方式不同;

2、空间大小不同;

3、能否产生碎片不同;

4、生长方向不同;

5、分配方式不同;

6、分配效率不同;    

       栈是一块连续的内存空间,具有后进先出的特点因此不存在内存碎片,而且计算机底层直接提供支持,分配效率高。无需程序员管理,编译器会自动申请和释放。

       堆的管理方式一般是采用链表管理可用的内存块,当用户申请一块内存时,系统从可用内存块中查找一块满足要求的内存空间分配给用户使用;用户释放内存后,系统将其回收。因此堆的内存管理需要由程序员来进行,分配效率不如栈。

三、字符串赋值给指针变量的告警

       在用g++作编译器时,将字符串常量赋值给指针变量将得到warningdeprecated conversion from string constant to 'char *'的警告。例如:char*ptrSt = “hello”;

这是因为将字符指针变量ptrSt指向一个位于常量区的字符串常量“hello”。如果在运行时修改ptrSt指向内存的值,例如:ptrSt[0]= 'j',将会抛出异常,在linuxg++下,抛出了“Segmentation fault”的异常。

       因此我们在将一个字符串常量赋值给字符指针变量时,应该将该变量限定为const型,即const char*。如果需要在代码中修改字符指针指向的变量的值,应该采用如下两种方式:


1. chars[] = “hello”;
2. char*ptrSt = s;

或者


1. char*ptrSt = (char*)malloc(sizeof(char) * 6);
2. strcpy(ptrSt,“hello”);

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值