[Cherno C++ 笔记 P1~P10]安装、链接器、变量、函数、头文件
[Cherno C++ 笔记 P1~P10]安装、链接器、变量、函数、头文件
- 系列博客
- 前言
- 视频链接
- P1~P4 安装部分
- P5 C++是如何工作的
- 第一个C++程序
- 代码如何编译为二进制文件
- 第一个函数
- 将函数放在其他文件中
- P6 C++编译器是如何工作的
- C++编译器实际上负责什么?
- P7 C++链接器是如何工作的
- 什么是链接
- 链接错误
- 未解决的外部符号
- 有重复的符号
- P8 C++变量
- P9 C++函数
- P10 C++头文件
- VS中的文件夹
- 第一个头文件
- #pragma once
- "" 和 <>
系列博客
[Cherno C++ 笔记 P1~P10]安装、链接器、变量、函数、头文件
[Cherno C++ 笔记 P11~P20]判断,循环,指针,引用,类
[Cherno C++ 笔记 P21~P30]static,枚举,构造函数,析构函数,继承,虚函数,接口,可见性
[Cherno C++ 笔记 P31~P40]数组、字符串、CONST、mutable、成员初始化列表、三元操作符、创建初始化对象、new关键字、隐式转换与explicit
[Cherno C++ 笔记 P41~P50]运算符重载、this、生存期、智能指针、复制与拷贝构造函数、箭头操作符、动态数组、std::vector、静态链接、动态库
前言
这个系列的视频需要一些基础,最好是学过C。
视频链接
P1 欢迎来到C++
P2 Windows 上安装C++
P3 Mac上安装C++
P4 Linux上安装C++
P5 C++是如何工作的
P6 C++编译器是如何工作的
P7 C++链接器是如何工作的
P8 C++变量
P9 C++函数
P10 C++头文件
P1~P4 安装部分
安装部分网上也有很多,安装也简单。
现在又很多工具可以用来写C++,这里推荐使用vs。
P5 C++是如何工作的
第一个C++程序
#include<iostream>int main()
{std::cout << "Hello world!" << std::endl;std::cin.get();
}
#include<iostream>
叫做预处理语句编译器收到源文件后,会预先处理,找到<>中的文件,然后拷贝到这个位置。
main
是程序的入口,计算机从这个函数开始执行代码。在这里,main函数的返回类型是int,但是代码中没有返回任何东西,这是因为main函数是特殊的,它不一定需要返回值。没有写return进行返回的话,它会默认返回了0。
<<
符号叫做重载运算符,可以理解为一个函数。
视频有很大一段在讲vs的相关设置,感兴趣的话可以观看视频。
代码如何编译为二进制文件
项目中的每一个cpp文件都会被编译,但是头文件不会被编译,头文件的内容在预处理时包含到了cpp中。
每一个cpp文件都被编译为object file(目标文件)vs生成的文件后缀为.obj,我们需要将这些文件合并成一个执行文件,链接(Link)会将所有的obj文件黏合在一起,合并成一个.exe文件。
第一个函数
void Log(const char* message) {std::cout << message << std::endl;
}int main()
{std::cout << "Hello world!" << std::endl;Log("Hello World!");std::cin.get();
}
将函数放在其他文件中
在源文件中新建一个Log.cpp
#include<iostream>void Log(const char* message) {std::cout << message << std::endl;
}
将Log函数放在其他地方后,main并不知道发生了这样的改变,它找不到叫做Log的函数,这时进行编译会报错。
我们需要在main所在的文件中声明Log函数存在
#include<iostream>void Log(const char* message);int main()
{std::cout << "Hello world!" << std::endl;Log("Hello World!");std::cin.get();
}
声明:
声明表示这个符号、函数是存在的。void Log(const char* message);
就是一个声明,它没有函数体。
定义:
定义是说明这个函数到底是什么,是函数的函数体。
在构建整个项目时,所有.cpp文件都会被编译,链接器会找到正确的Log函数的定义在哪里,如果找不到定义,会报链接错误。
P6 C++编译器是如何工作的
C++编译器实际上负责什么?
C++编译器只负责一件事,将文本文件(我们写的代码)转换成称为目标文件的中间格式。
这些obj文件可以传递到链接,链接可以做它所有要链接的事情。
编译器在生成这些obj时:
- 预处理代码。这意味着所有的预处理器语句都会先处理。
- 记号化和解析。将文本转换为编译器真正能够理解和推理的格式。这创建了所谓的抽象语法树。语法树一旦被创建,编译器就可以开始实际生成代码
与java不同的是,c++并不关心文件,文件只是提供给编译器源代码的一种方式。 可以随便创建一个文件(如xxx.hello_world),只要告诉编译器这是一个c++文件,就可以进行编译。
我们提供给编译器的每个c++文件,编译器都将把文件变成翻译单元(一个cpp文件并不一定对应一个翻译单元),翻译单元生成一个obj文件。
obj文件中都是机器码,我们可以在vs中查看汇编语句。
- 首先,我们在这里打一个断点
- 进行调试
- 右键,转到反汇编
- 可以看到相应语句转换为的汇编语句
可以在属性中开启优化、关闭优化, 对比一下生成的汇编语句
P7 C++链接器是如何工作的
什么是链接
链接时一个过程,当我们编译好源文件,我们需要通过一个叫做链接的过程,现在链接的主要任务时找到每个符号和函数所在的地方,并把它们链接起来。
多个翻译单元之间并不互通,我们需要一种方法把这些文件连接起来成一个项目。即使只有一个翻译单元,也需要将main函数连接起来,这就是链接器的主要目的和要做的事情。
链接错误
未解决的外部符号
当链接器找不到确切定义时发生。
我们写一个死代码,它没有被任何函数调用,其中Log函数虽然被定义但并不存在。在这里依然会报错。
虽然我们没有使用Multiply函数,但是在技术上来讲,我们有可能会用到这个函数,所以链接器需要链接到它,所以会报错。
我们使用static将Multiply函数限制在该文件中使用,由于我们没有使用该函数,所以不再报错。
在这里,我们并没有真正导入我们所写的返回void的Log,这里返回为int的函数由于没有明确的定义,所以会引发报错。
有重复的符号
如果我们的函数或变量具有相同的名字或签名,链接器会不知道该链接哪一个。
在下面这个例子中,我们可以看到,即使没有申明,两个相同的函数放在不同的文件中,依然会报错。
P8 C++变量
略
P9 C++函数
略
P10 C++头文件
VS中的文件夹
VS中的文件夹并不是真正的文件夹,你可以在资源管理器中看到并没有这些文件夹。这些文件夹实质上是过滤器。
第一个头文件
Log.cpp
#include<iostream>void Log(const char* message) {std::cout << message << std::endl;
}
Log.h
#pragma once
void Log(const char* message);
Main.cpp
#include<iostream>
#include"Log.h"int main()
{Log("Hello world!");std::cin.get();
}
通过#include"Log.h"
导入头文件,将头文件中的文本粘贴到该位置。
#pragma once
progma once: 只包括这个文件一次
#pragma once
监督这个头文件,阻止我们单个头文件被多次包含,并转换为单个翻译单元。
这里我想用集合来举例说明:
我们现在有两个集合A{a,b,c,d}和B{c,d,e,f}(a,b,c,d,e,f均为.h文件),当我们同时需要调取A和B时,#pragma once
的作用就是将A和B取并集为{a,b,c,d,e,f}而不是简单的合并成{a,b,c,d,c,d,e,f}。
可是使用另一种方法实现相同的功能
#ifndef _LOG_H
#define _LOG_Hvoid Log(const char* message);#endif
#ifndef
检查看是否有一个叫做_LOG_H的符号被定义了,如果没有被定义,则继续,如果被定义,则禁止。
“” 和 <>
在编译程序时,<>和""表示两种不同含义。
“”用来包含相对于当前文件的文件
<>用来搜索包含路径中的文件
“”也具有<>的功能
[未完待续]
[Cherno C++ 笔记 P1~P10]安装、链接器、变量、函数、头文件相关推荐
- 【软件开发底层知识修炼】十 链接器-main函数不是第一个被执行的函数
上一篇文章,大概了解了链接器的工作内容就是:符号解析和重定位.点击上一篇文章查看:点击查看. 本片文章其实还是围绕链接器来学习.只不过不是很明显,当你学到下一篇文章时,就明白了. 本篇文章来弄明白一个 ...
- 【软件开发底层知识修炼】九 链接器-可重定位文件与可执行文件
上几篇文章学习了Binutils辅助工具里面的几个实用的工具,那些工具对于以后的学习都是非常有帮助的,尤其是C语.C++语言的学习以及调试是非常有帮助的.点击链接查看上一篇文章:点击查看 本篇文章开始 ...
- C++ 笔记(25)— 理解 C++ 中的头文件和源文件的作用
1. C++ 编译模式 通常,在一个 C++ 程序中,只包含两类文件: .cpp 文件,被称作 C++ 源文件,里面放的都是 C++ 的源代码 .h 文件,被称作 C++ 头文件,里面放的也是 C++ ...
- noi linux下如何安装视频播放器 和 播放swf文件的工具
因为考试需要,孩子们必须要在赛前掌握使用noilinux了,可是使用起来诸多不方便,这不,在linux里用什么看视频和swf教程呢. 下面提供我搜集到的方法: 1.用noilinux自带的smplay ...
- 学习笔记15-C语言-预处理指令、条件编译、头文件
预处理指令: 程序猿编写的代码不是标准C代码,并不能被真正的编译器索编译,需要一段程序把代码翻译一下. 翻译的过程叫做预处理,被翻译的代码叫做预处理指令,以#开头的都是预处理指令查看预处理的过程:gc ...
- 《Python数据分析基础教程:NumPy学习指南(第2版)》笔记5:第三章 常用函数1——文件读写、算术平均值、最大值最小值、极值
本章将介绍NumPy的常用函数.具体来说,我们将以分析历史股价为例,介绍怎样从文件中载入数据,以及怎样使用NumPy的基本数学和统计分析函数.这里还将学习读写文件的方法,并尝试函数式编程和NumPy线 ...
- 解决方案资源管理器中没有头文件源文件
转自:http://blog.csdn.net/wsj998689aa/article/details/40051287 我们操作VS的时候,正常情况下,解决方案窗口中,项目内文件的布局如下: 可是, ...
- 易语言静态连接器提取_易语言静态编译链接器切换工具
使用说明 将exe程序和"链接器目录配置.ini"文件,复制到易语言安装目录的"tools"文件夹下 并且对"链接器目录配置.ini"进行修 ...
- C++链接器工具错误:LNK2001, LNK2019
这是归属于链接器工具错误 这一类. 无法解析的外部符号"symbol" 代码引用了链接器无法在库和对象文件中找到的内容(如函数.变量或标签). 可能的原因 代码请求的内容不存在(例 ...
最新文章
- java extjs如何使用_ExtJS初探:在项目中使用ExtJS
- parted磁盘分区与GPT
- python在匿名函数作和_跟光磊学Python开发-匿名函数函数和高阶函数
- (7) hibernate之级联cascade和关系维持inverse
- easyui 排序实现
- 世界公认的第一商人——成就犹太商人的15个信条
- android jar包 权限,Android系统启动执行jar程序
- mac apache php.ini,Mac自带的Apache使用详解
- oracle高效分页存储过程(百万数据级)
- 1811114每日一句
- 【自动驾驶】ROS机器人操作系统总结
- R语言绘图—一键添加显著性
- markdown学习笔记(1):如何将.md文件转换为pdf
- 百度为手游盛世添把火
- 虹科Linux远程桌面服务器助力工业生产管理
- input 表单的type属性
- 数字信号处理总结之共轭对称性_复变函数积分的共轭=共轭的积分
- 2019年最值得期待的区块链项目:PlusFo到底行不行?
- RDKit | 子结构搜索和MCS算法
- web前端期末大作业——基于Bootstrap响应式汽车经销商4S店官网21页
热门文章
- bzoj 3521: [Poi2014]Salad Bar
- Foehn Phenomena
- MAE源代码理解 part1 : 调试理解法
- 蓝牙扫描枪直连蓝牙打印机
- 2021年中国物联网通信板块现状及重点企业对比分析(移远通信VS广和通VS和而泰VS拓邦股份VS移为通信)[图]
- videobuf2相关的videobuf-vmalloc.c 中内存分配kmalloc使用
- 项脊轩志(明 归有光)
- Meting-JS APlayer丨网页音乐播放器
- HPC 网络技术 — Overview
- 【mmaction2 slowfast 行为分析(商用级别)】总目录