联合编程;编译器
- 操作系统下的内存分配:程序怎么放到内存的?
- 定义和声明
- extern
-
- 变量的定义
- 如何在C++代码中调用C语言的函数
- 用extern 关键字,把函数声明成C语言风格
- #ifdef __cplusplus extern "C" #endif
- 头文件和源文件
-
- 头文件引用,重复定义问题 (1)
- 头文件引用 重复定义的问题(2)宏定义方式解决
- LNK4042错误
- 创建自己的SDK——流程
- 创建自己的项目类型
- 单一性规则 One Definition Rule
-
- 转换单元
- 未定义行为
- 单一性规则 ODR
-
- 举例1:非inline类型
- 举例2:inline类型
- 举例3:inline类型
- 单一性规则 ODR
-
- (1)对于const类型的常量,在不同转换单元可以重复定义;
- (2)对于static类型的常量,在不同转换单元可以重复定义;对比inline类型
- 名称的链接属性
- #define 用法
-
- (0)配合#ifdef 来检测宏
- (1)C语言中经常用#define来定义常量
- (2)定义复杂表达式宏
- (3)#undef 取消宏定义
- 预处理指令逻辑
-
- #ifdef #ifndef #else #elif #endif
- 预定义宏
-
- 标准预定义标识符
-
- _ _ func_ _
- _ _ DATE_ _ , _ _ TIME_ _ , _ _ FILE_ _ , _ _ LINE_ _
- _ _ cplusplus
- MSVC的预定义宏
- assert
- static_assert C++17的新语法
操作系统下的内存分配:程序怎么放到内存的?
注:x86 32位windows
(1)全局变量区:全局变量、static关键字定义的变量
(2)代码区:其它代码部分
(3)堆区:new的内存空间
(4)栈区:局部变量
编译完成后,这四个是挨着的。放到内存中也是
默认情况下每个程序(线程)独占内存(虚拟内存)
定义和声明
只有返回类型+函数名称+形参,没有具体实现的写法,就是函数声明;
例子:
int add(int a, int b);//函数声明
int main()
{
cout << add(1, 2);//调用
}
int add(int a, int b)//函数定义
{
return a + b;
}
编译器翻译上面面代码时,如果没有函数声明,调用时就会找不到(更准确的来说是不知道add返回什么类型,需要什么类型的参数);
编译器只负责翻译,不负责运行;
函数具体的实现是在运行时体现;
而返回类型和参数类型等是编译时就必须要明确,比如要判断调用是不是可行的;
函数声明就是为了告诉编译器函数的接口,然后编译器就知道函数被调用得对不对。
如此说来 函数声明时的形参名称也是可以不写的
int add(int, int);//函数声明
int main()
{
cout << add(1, 2);//调用
}
int add(int a, int b)//函数定义
{
return a + b;
}
但最好写上,因为编译器不看,人得看。
补充:
相同的函数声明可以多次出现,因为声明只是给编译器看,不会说让运行时出现冲突。
int add(int, int);//函数声明
int add(int, int); int add(int, int);
int main()
{
cout << add(1, 2);//调用
}
int add(int a, int b)//函数定义
{
return a + b;
}
extern
变量的定义
int a;
变量的声明
注:只在全局有效
extern int a;
如何在C++代码中调用C语言的函数

用extern 关键字,把函数声明成C语言风格
用法1:
extern “C” { int add(int a,int b); }
用法2:
extern “C” { #include “myC.h” }
注:
由于C++支持函数的重载,所以编译时会对函数名进行较为复杂的修改
C语言就很简单,比如我定义一个int add();编译器会处理成int _add();
#ifdef __cplusplus extern “C” #endif
略
头文件和源文件
头文件 .h 放声明
源文件 .cpp .c 放定义
.c源文件里只能写c语言代码。
举例:
xx.c
#include
int main()
{
std::cout<<“xxx”;
}
//虽然引用了头文件,但由于这段代码在.c文件中,所以还是会报错
//放回到.cpp文件中可以正常运行
做一个自己的库,包含头文件和源文件;
头文件里面放声明,源文件里面放定义
用这个库的时候,引用一下头文件就可以了,原因在于,引用了头文件相当于把头文件里面的声明放到那个位置,那么那个位置后面的函数就可以去使用这些声明。而编译完成后,整个程序是包含了库的源文件的内容的,自然也就能够正常运行。
代码到程序的过程:
(1)源文件编译成.obj 或 .o
(2)再把这些目标文件链接到一起
(3)头文件不会主动参与编译过程,除非被引用;
头文件引用,重复定义问题 (1)
编译时报错:xxx已被定义
函数名不可重复,除非是重载函数,即使在不同文件中,只要在同一个工程,就不可重复(不包括被命名空间限制、类函数等情况)
变量名同样的不可重复。
解决方法:
(1)不在头文件里写定义
(2)带static关键字的静态函数和静态变量
注意:
例如:头文件被多次引用,其中有静态变量的定义;由于其只在本地有效的特点,这就相当于在不同地方定义了多个这样的变量;
比方说:头文件里写了static int a{100};那么多次引用得到的初值也都是100,一个地方修改值,不会影响另一个地方(引用得到的静态变量)的值
这里举个例子(不过还是很绕,反正就是那个意思):
//mlib.h
extern int a;
void aaa();
//mlib.cpp
#include "mlib.h"
int a{
100 };
void aaa()
{
a++;
}
//main.cpp
#include "mlib.h"
int main()
{
aaa();
cout << a;
}
输出a:101
因为先调用了函数aaa,使得a的值加1;
而如果是静态的变量
//mlib.h
static int a;
void aaa();
//mlib.cpp
#include "mlib.h"
void aaa()
{
a++;
}
//main.cpp
#include "mlib.h"
int main()
{
aaa();
cout << a;
}
输出a:100
虽然这里也是先调用函数aaa,但mlib.cpp里的a和main.cpp里的a是不一样的
同时也可通过汇编代码看到两个a的地址是不一样的:
void aaa

最低0.47元/天 解锁文章
3万+

被折叠的 条评论
为什么被折叠?



