您的位置:首页 > 编程语言 > C语言/C++

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

2013-03-02 16:38 190 查看
本文介绍在Ubuntu12.10,g++环境下C++内存分配问题。并由此解释在用g++编译时,字符串常量赋值给字符指针类型时提示“warning:deprecated
conversion from string constant to 'char *'”警告的原因。

一、C++内存分配



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

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <malloc.h>

using namespace std;

int quanju;/*全局变量,全局区/静态区(static)*/
void fun(int f_jubu); /*代码区*/
int main(void)
{
int m_jubu;/*栈区(stack)*/
static int m_jingtai;/*静态变量,全局区/静态区(static)*/
const int conInt = 5;/*main中的局部变量,位于栈区,被const修饰,变量值不可变*/
static const int sconInt = 6;/*常量,位于常量区*/
char *m_zifum,*m_zifuc = "hello";/*指针本身位于栈。指向字符串"hello",位于代码区/常量区*/
char* zifuc_hw = "hello world";/*字符串"hello world",位于常量区*/

/*正确的赋值方式*/
char *zif = (char*)malloc(sizeof(char) * 6);
strcpy(zif, "hello");
cout<<zif<<endl;
cout<<m_zifuc<<endl;

void (*pfun)(int); /*栈区(stack)*/
int (*pmain)(void);
pfun=&fun;
pmain = &main;
m_zifum = (char *)malloc(sizeof(char)*10);/*指针内容指向分配空间,位于堆区(heap)*/
pfun(1);
cout<<"全局变量		:"<<&quanju<<endl;
cout<<"main静态变量		:"<<&m_jingtai<<endl;
cout<<"main字符串常量(hello)	:"<<(void*)m_zifuc<<endl;
cout<<"main字符串常量(h w)	:"<<(void*)zifuc_hw<<endl;
cout<<"main局部变量(const修饰):"<<&conInt<<endl;
cout<<"main静态整型常量	:"<<&sconInt<<endl;
cout<<"fun函数代码地址		:"<<(void*)pfun<<endl;
cout<<"main函数代码地址	:"<<(void*)pmain<<endl;
cout<<"main字符串(堆分配)	:"<<(void*)m_zifum<<endl;
cout<<"main函数函数指针变量	:"<<&pfun<<endl;
cout<<"main局部变量		:"<<&m_jubu<<endl;
cout<<"main局部变量		:"<<&m_zifuc<<endl;
cout<<"main局部变量		:"<<&m_zifum<<endl;
return 0;
}
void fun(int f_jubu)
{
static int f_jingtai;
char* f_zifuc = "hello";
cout<<"fun静态变量		:"<<&f_jingtai<<endl;/*静态变量,位于静态区*/
cout<<"fun字符串常量(hello)	:"<<(void*)f_zifuc<<endl;/*常量,位于常量区,同main中的“hello”地址相同*/
cout<<"fun形参变量		:"<<&f_jubu<<endl;/*栈区(stack),但是与主函数中m_jubu位于不同的栈*/
cout<<"fun局部变量		:"<<&f_zifuc<<endl;
}


实验结果:

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++作编译器时,将字符串常量赋值给指针变量将得到“warning:deprecated
conversion from string constant to 'char *'”的警告。例如:char*ptrSt
= “hello”;
这是因为将字符指针变量ptrSt指向一个位于常量区的字符串常量“hello”。如果在运行时修改ptrSt指向内存的值,例如:ptrSt[0]=
'j',将会抛出异常,在linux的g++下,抛出了“Segmentation
fault”的异常。

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

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


或者

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


Reference

1.C++内存分配方式详解——堆、栈、自由存储区、全局/静态存储区和常量存储区
2.C/C++编程:结合内存分布图分析内存问题
3.关于程序设计的内存分配问题
4.关于函数字符数组调用的问题(没有搞清指针的概念)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: