#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
//extern int a = 10; 默认外部链接
int a = 10; //全局区
//静态全局变量是内部链接
static int b = 20; //静态区
//内部链接和外部链接有什么区别?
//1. 如果变量是内部链接的话,那么此变量只能在当前文件内访问
//2. 如果是变量是外部链接的话,那么此变量可以被其他文件使用
//1. 全局静态变量和局部静态变量都存储在静态区,都是在程序运行期间都是合法有效
//2. 局部静态变量符号的可见范围仅限于当前函数内部,全局静态变量可见范围从定义到文件结尾
//头文件不要放定义,只能放声明
void test01()
{
static int c = 30; //静态区
}
//头文件不参与编译,每一个.c文件,我们叫做一个编译单元
//编译器独立编译每一个.c文件
void test02()
{
//声明,表示告诉编译器这个符号是存在的,你让我先编译通过,让连接器去找到底这个符号在那
extern int g_a;
printf("g_a = %d\n", g_a);
}
//--------------------------------------
//常量区 字符串常量 全局const变量
//1. const全局和局部变量区别?
//const全局变量在常量区,不能修改(直接或者间接)
const int g_c = 100;
void test03()
{
//直接修改不行
//g_c = 200;
//间接修改也不行
int *p = (int *)&g_c;
*p = 200;
//全局const放在常量区,一旦初始化,不能修改
}
//2. const局部变量
void test04()
{
//栈上
const int a = 100;
//a = 200;
int *p = (int *)&a;
*p = 200;
printf("a = %d\n", a);
}
void test05()
{
//"hello world!" char*类型字符串
#if 0
char *p = "hello world!";
printf("%d\n", &"hello world!");
printf("%d\n", p);
printf("p = %s\n", p);
p[0] = 'A';
printf("p = %s\n", p);
#endif
char *p1 = "hello world!";
char *p2 = "hello world!";
printf("p1 = %d\n", p1);
printf("p2 = %d\n", p2);
}
int main(){
//test04();
test05();
system("pause");
return EXIT_SUCCESS;
}
全局静态区内的变量在编译阶段已经分配好内存空间并初始化。这块内存在程序运行期间一直存在,它主要存储全局变量、静态变量和常量。
注意:
- 这里不区分初始化和未初始化的数据区,是因为静态存储区内的变量若不显示初始化,则编译器会自动以默认的方式进行初始化,即静态存储区内不存在未初始化的变量。
- 全局静态存储区内的常量分为常变量和字符串常量,一经初始化,不可修改。静态存储内的常变量是全局变量,与局部常变量不同,区别在于局部常变量存放于栈,实际可间接通过指针或者引用进行修改,而全局常变量存放于静态常量区则不可以间接修改。
- 字符串常量存储在全局/静态存储区的常量区。
示例代码:
int v1 = 10;//全局/静态区
const int v2 = 20; //常量,一旦初始化,不可修改
static int v3 = 20; //全局/静态区
char *p1; //全局/静态区,编译器默认初始化为NULL
//那么全局static int 和 全局int变量有什么区别?
void test()
{
static int v4 = 20; //全局/静态区
}
加深理解:
char* func()
{
static char arr[] = "hello world!"; //在静态区存储 可读可写
arr[2] = 'c';
char* p = "hello world!"; //全局/静态区-字符串常量区
//p[2] = 'c'; //只读,不可修改
printf("%d\n",arr);
printf("%d\n",p);
printf("%s\n", arr);
return arr;
}
void test()
{
char* p = func();
printf("%s\n",p);
}
字符串常量是否可修改?字符串常量优化:
ANSI C中规定:修改字符串常量,结果是未定义的。
ANSI C并没有规定编译器的实现者对字符串的处理,例如:
- 有些编译器可修改字符串常量,有些编译器则不可修改字符串常量。
- 有些编译器把多个相同的字符串常量看成一个(这种优化可能出现在字符串常量中,节省空间),有些则不进行此优化。如果进行优化,则可能导致修改一个字符串常量导致另外的字符串常量也发生变化,结果不可知。
所以尽量不要去修改字符串常量!
总结
在理解C/C++内存分区时,常会碰到如下术语:数据区,堆,栈,静态区,常量区,全局区,字符串常量区,文字常量区,代码区等等,初学者被搞得云里雾里。在这里,尝试捋清楚以上分区的关系。
数据区包括:堆,栈,全局/静态存储区。
- 全局/静态存储区包括:常量区,全局区、静态区。
- 常量区包括:字符串常量区、常变量区。
代码区:存放程序编译后的二进制代码,不可寻址区。
可以说,C/C++内存分区其实只有两个,即代码区和数据区。
网友评论