C++相关个人注解(未完待续)

X86_64 下 Linux 进程的默认内存布局形式

C++相关个人注解(未完待续)_第1张图片

内存顺序

1、除了堆栈段以外,其他的段的数据排列顺序都是从小到大
2、内存申请存在128k对齐的限制,所以heap、bss、data段如果一次申请内存超过128k,必然分配在mmp中,如果是stack的话就直接分配失败

static

1、通常作为静态变量的前缀,静态变量在系统装载程序时被放置于数据段(DATA | BSS,如果变量值已初始化则放置于DATA段,否则BSS)
2、在一个C++源文件中被static修饰的变量无法在另一个C++源文件通过extern来引用

extern

1、头文件中的函数隐式添加关键字extern
2、被const修饰的变量往往隐式地被编译器添加static,所以一般会选择将其放置于头文件中。另一种用法则是显示地添加extern关键字,例如:
a.cpp文件
extern const int N=100;
b.cpp文件
extern const int N;
int num = N;

但是这种用法对于声明数组不一定有效,例如:
a.cpp文件
extern const int N=100;
b.cpp文件
extern const int N;
int num[N];
如上所示的情况下,在文法检查阶段就直接报错。而这样就可以:
a.cpp文件
extern const int N;
b.cpp文件
extern const int N=100;
int num[N];

3、如果在不同源文件中都定义了extern int XXX; 那么这些变量中必须有且仅有一个被初始化

#include

1、#include的作用基本类似于#define,基本等同于把头文件内容全部复制过来。因此如果头文件中包含变量且该头文件被不同源文件包含,就会引起变量重复定义。


连接

首先按照namespace划分:namespace_1、namespace_2、namespace_3

namespace_1{

namespace_2::B b

namespace_3::C c

}

namespace_2{

namespace_3::C c

namespace_1::Aa

}

namespace_3{

namespace_1::Ad

}

所以一种可用的连接顺序为 namespace_1,namespace_2,namespace_3,namespace_1

总结:

说了这么多其实关键在于理解编译链接的原理:

预编译:各种宏展开以及文件包含

编译:各个源文件的编译是独立的,每个文件在首先进行文法检查,然后根据当前的变量函数建立标识符

链接:根据各个文件的标识符进行重复检查、对extern修饰的变量函数在所有文件的标识符中查找(任何extern修饰的未初始化的变量都表示该变量实际在别处定义,包括同一文件下。但如果该变量被extern修饰且在声明处初始化,说明当前定义有效)



你可能感兴趣的:(C++,编译器)