如果要加入此计划:
1、 方式1 :加入 QQ 群: 93684322 。
2、 方式2 :加入 CSDN 群组: DS计划 。
1.1 变量存储域
1.1.1 一个示例
pang123hui首先提供了一个网上流传的学习代码示例:
int a = 0; //全局区
void main()
{
int b; //栈
char s[] = “abc”; //s在栈,abc在文字常量区
char *p1,*p2; //栈
char *p3 = "123456"; //123456在常量区,p3在栈上
static int c =0; //全局区
p1 = (char *)malloc(10); //p1在栈,分配的10字节在堆
p2 = (char *)malloc(20); //p2在栈,分配的20字节在堆
strcpy(p1, "123456"); //123456放在常量区
}
这个代码示例中出现了“全局区”,“栈”,“文字常量区”,“堆”等词语。为了统一,我们使用《C专家编程》中的说法:堆栈段,BSS段,数据段,文本段。
各个段的作用如下:
1、 文本段:包含程序的指令,它在程序的执行过程中一般不会改变。
2、 数据段:包含了经过初始化的全局变量和静态变量,以及他们的值。
3、 BSS段:包含未经初始化的全局变量和静态变量。
4、 堆栈段:包含了函数内部声明的局部变量。
当然,上面段的作用不仅于此,具体的作用会在下面的知识点中介绍。
1.1.2 通过代码测试变量的存储位置
Linux下可以通过系统命令“size”查看可以执行程序各个段的大小。但是,可执行程序中的段结构和运行中程序在内存中的段结构并不完全相同,但是有一定的映射关系。具体如下图所示(图片信息来自《C专家编程》):
下面通过代码示例和“size”来研究变量的存储区域。
test.c
int main()
{
return 1;
}
编译,并且查看可执行程序各个段的大小:
更改test.c:
int g_data;
int main()
{
return 1;
}
编译,并且查看可执行程序各个段的大小:
可以发现,文本段,数据段都没有发送变化,而BSS段增加了4个字节。
结论1:未初始化的全局变量保存在BSS段中
继续:
int g_data = 1;
int main()
{
return 1;
}
编译:
可以发现,BSS段和文本段相同,而数据段增加了4个字节。
结论2:经过初始化的全局变量保存在数据段中
继续:
int main()
{
static int g_data;
return 1;
}
编译:
可以发现,文本段,数据段都没有发送变化,而BSS段增加了4个字节。
结论3:未初始化的静态变量保存在BSS段中
继续:
int main()
{
static int g_data = 1;
return 1;
}
编译:
可以发现,BSS段和文本段相同,而数据段增加了4个字节。
结论4:经过初始化的静态变量保存在数据段中
继续:
int main()
{
int i_data = 1;
return 1;
}
编译:
可以发现,BSS段和和数据段相同,而文本段增加了16个字节。局部变量会在执行的时候在堆栈段中生成,函数执行完毕后释放。
结论5:函数内部声明的局部变量保存在堆栈段中
继续:
const int g_data = 1;
int main()
{
return 1;
}
编译:
把全局变量定义为“const”后,也许你会感到奇怪,怎么BSS段和数据段都没有发生变化,而文本段却增加了4个字节。
结论6:const修饰的全局变量保存在文本段中
那么,const的局部变量?
继续:
int main()
{
const int i_data = 1;
return 1;
}
编译:
结论7:const修饰的局部变量保存在堆栈段中
继续:
char *pstr = "";
int main()
{
return 1;
}
编译:
在做一下更改:
char *pstr = "123456789";
int main()
{
return 1;
}
编译:
可以发现,前后数据段和BSS段大小均未发生变化,而文本段增加了9个字节。
结论8:字符串常量保存在文本段中
1.1.3 结论
1、 经过初始化的全局变量和静态变量保存在数据段中。
2、 未经初始化的全局变量和静态变量保存在BSS段。
3、 函数内部声明的局部变量保存在堆栈段中。
4、 const修饰的全局变量保存在文本段中,const修饰的局部变量保存在堆栈段中。
5、 字符串常量保存在文本段中。
1.1.4 扩展阅读
《C专家编程》第6章——详细介绍各个段的作用。