联合编程(C语言和C++);编译器 ---入门

联合编程;编译器

  • 操作系统下的内存分配:程序怎么放到内存的?
  • 定义和声明
  • 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
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值