LearnCpp-chapter1

LearnCpp-chapter1

https://www.learncpp.com

0.5 介绍compiler, linker, and libraries

Development-min

Step 4: Compiling your source code

为了编译C++程序,我们需要一个编译器。编译器主要是对每一个.cpp文件做两件事情:

  1. 它检查你的代码是否符合C++的规则。如果不符合,就会报错(同时返回相应的行号)来帮助你确定什么需要修改,同时停止编译
  2. 它将C++源代码翻译成机器代码文件(叫做:object file)。object file的名字通常是这种形式:name*.o*** 或者 name*.obj***(其中name与.cpp文件的name是对应的)。

例如:下面的三个.cpp的源文件,编译之后形成:

The compilation process


Step 5: Linking object files and libraries

编译器compiler 编译完成后,生成若干的 object files。接下来就需要链接器Linker出马了。linker的工作主要有三方面:

  1. 将所有的object files(编译之后生成的)合并成为一个可执行程序executable program

    LinkingObjects-min

  2. 此外,linker还可以链接库文件library files(library files是一个已经预编译好的代码经过“打包”,在其他程序中重用)

    C++有有一个扩充的库,叫做:标准库C++ Standard Library。它提供额外的功能性库,比如我们常用的iostream library

    你可以有选择性的去链接其他库,比如当你想写一个播放声音的程序。你肯定不想从头到尾的去写如何去读取文件、检查文件是否有效… 这时候,我们只需要下载相关的库进行利用就方便很多了。

  3. 连接器会确保所有的跨文件依赖项都正确的解析了。

    例如:

    如果你在一个.cpp文件中定义了"A",然后在另一个.cpp文件中去使用"A"。linker就会将这两个文件联系起来。如果链接不成功,就会报错并且连接终止

只要linker成功的完成所有的“object files 和 libraries ”的链接工作,你就会得到一个可执行文件,然后你就可以运行它。

Makefile
【注】有些开发环境使用Makefile,它是一个描述如何构建一个程序的文件(哪一个文件要编译&链接,或者以不同方式处理)它是一个强大的工具。但是在本系列课程我们不回去讲解它。

Steps 6 & 7: Testing and Debugging

如果你的可执行程序没有按照预期的工作,那么你就需要调试。

Integrated development environments (IDEs)

【note】step3、4、5、7(editor, compiler, linker, debugger)都是需要软件的。

当然,你可以每一部分都是用独立的软件,但是有这样的一个软件包:integrated development environment (IDE)集成开发环境 将上面四步一体化。


0.6 compling your first program

Console projects

控制台项目没有graphical user interface (GUI)图形用户界面,它在控制台中打印text,从输入设备键盘读取信息。并且被编译成独立的可执行文件。

Workspaces / solutions

当创建一个项目时,许多IDE会自动给这个项目创建一个 “workspace” 或 “solution” 。

workspace or solution:是一个可以容纳多个相关的项目的container。(例如,你正在写一个游戏,你想有一个单人 与 多人分开的可执行文件,那就需要创建两个项目。但是将这两个项目分开始没有意义的,因为它们属于同一个游戏的。所以,最好的就是每一个都被配置为单个工作空间/解决方案中的 一个单独项目。)

0.8 C++中常见问题

General run-time issues

  1. 当执行程序时,控制台窗口闪烁,然后立即关闭?

    • 1、首先确保下面的这几行在你的源程序的最上部(visio studio 用户,请确认如果有 #include “pch.h” or #include “stdafx.h” ,那么让它在最顶顶顶部的)
    #include <iostream>
    #include <limits>
    
    • 2、在main()函数中的结束部分(但要在return 语句之前)添加如下:
    std::cin.clear(); // reset any error flags
    
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // ignore any characters in the input buffer until we find an enter character
    
    std::cin.get(); // get one more char from the user
    

    避免使用system("pause") 因为它只能在特定的操作系统中使用

  2. 运行程序,得到窗口,但没有输出?

    有可能是你的xx安全管家等拦截的。试着关闭它们,然后重新运行

  3. 程序编译成功,但是没有正确工作?

    去debug它

General compile-time issues

  1. 当编译程序时,得到一个未解析的外部符号:_main or _WinMain@16 ?

    说明你的编译器找不到main()函数。

Visual Studio issues

  1. 使用Microsoft Visual c++进行编译时,得到C1010 fatal error,并且伴随着提示信息,如:"c:\vcprojects\test.cpp(263) :fatal error C1010: unexpected end of file while looking for precompiled header directive"

    答:这种问题出现在:当microsoft visual c++编译器被设置为使用预编译头文件,但您的c++代码文件中有一个(或多个)没有将#include “stdafx.h” or #include “pch.h”作为代码文件的第一行。

    建议:

    1. 在创建项目时,将预编译头 precompiled headers选项关闭。

    2. 如果您希望保持打开预编译头文件,要修复这个问题,只需找到产生错误的文件(在上面的错误中,test.cpp是罪魁祸首),并在文件的最顶部添加以下行:

      #include “pch.h”或者#include “stdafx.h”【老版本的VS使用“stdafx.h” ,当其中一个不起作用,可以换成另外一个】

      注意,每一个C++文件都是从这一行开始的。如果不想从这一行开始,那就在创建项目的时候关闭“预编译头文件”选项

  2. 出现错误:"1MSVCRTD.lib(exe_winmain.obj) : error LNK2019: unresolved external symbol _WinMain@16 referenced in function “int __cdecl invoke_main(void)” (?invoke_main@@YAHXZ)"

    答:您可能已经创建了一个Windows图形化应用程序,而不是控制台应用程序。重新创建项目,并确保将其创建为Windows(或Win32)控制台项目。

0.9 配置编译器:“生成(build)”配置

debug configuration :可以帮助你调试你的程序,而且也是IDE默认的。但是它会关掉所有的优化,包含调试信息(这会让你的项目变得很大、很慢)。

release configuration:当你将你的程序发布给公众的时候使用release模式。这个模式会优化项目的大小和它的性能,而且不会包含额外的调试信息。所以这种模式适用于:测试你的代码的性能.

0.10 配置编译器:编译器扩展

c++标准定义了关于程序在特定环境下应该如何表现的规则。在大多数情况下,编译器将遵循这些规则。然而,许多编译器实现自己对语言的更改,通常是为了增强与该语言的其他版本(例如C99)的兼容性,或者是出于历史原因。这些特定于编译器的行为称为编译器扩展(Compiler extensions)

编写使用编译器扩展的程序允许你编写与c++标准不兼容的程序。使用非标准扩展的程序通常无法在其他编译器上编译(这些编译器不支持相同的扩展),或者即使它们支持,也可能无法正确运行。

注意,编译器扩展通常是默认启用的,这对初学者是不友好的,因为它会让初学者觉得某些行为是符合官方C++的标准,但是实际上是因为编译器只是过于宽松。

因为,编译器扩展从来都不是必须的,如果开启可能让你误以为你写的代码是符合C++标准的。所以,建议,建议关闭编译器扩展。

0.11 配置编译器:warning和error

出现error提示:说明你写的代码可能不符合C++语言的标准。

出现warning提示:说明编译器认为你的代码的某些地方可能有些错误,但是编译器不能百分百确定。

好习惯:

不要让warning提示堆积,要尽你所能的去解决warning提示。

在大多数情况下出现的warning是需要我们尽量去解决的。但在极少数情况的warning提示,我们需要明确告诉编译器不要产生这个警告。C++官方不支持这样,但是有很多单独的编译器(如:visio studio xx 和GCC)会提供解决方案:利用不可移植 # pragma 指令 来暂时的关闭这个警告。

好习惯:

将你的经高级别调到最大,特别是在你学习的时候,他会帮你识别潜在的问题。

将warnings视为errors

如果在你学习的时候,最好告诉编译器让它把warning当做error对待,然后你就不得不去解决出现的warning了。

0.12 配置编译器: 选择一个C++标准

C++的标准有很多,如:C++98, C++03, C++11, C++14, C++17, 等. 通常情况,编译器的标准都是默认的,而不是最新的C++标准。如果你想使用指定的标准版本,需要手动设置。

正在制定中的标准的名字

有一些语言标准是按照他最终定案时候的年份(如,C++17是在2017年完成的)。但是,当一个新的语言标准正在制定ing的时候,我们不能确定它最终完成的时间。这个时候这个语言标准的名字 将会被最终完成时候的名字替代,(如,C++11在制作ing时,名字为C++1x,当最终完成的时候“C++1x”就会被替换),比如下面的一些:

  • c++1x = C++11
  • c++1y = C++14
  • c++1z = C++17
  • c++2a = C++20

所以,如果你看见C++1Z,这就代表C++17

【注意】:在VS xxxx系列的IDE中,是不能设置全局的语言标准的,你只能一个一个项目的去设置

1.1 语句与程序结构

Statements and the structure of a program

语句

**语句(Statements)**是一种指令类型,它使程序执行某些操作。它是最小的独立计算单元。在C++中,一个单独的语句就可能会被编译成很多机器语言指令。

下面列出了很多种语句:

  1. Declaration statements(声明语句)
  2. Jump statements(循环语句)
  3. Expression statements(表达式语句)
  4. Compound statements(复合语句)
  5. Selection statements (conditionals) (条件语句)
  6. Iteration statements (loops) (循环语句)
  7. Try blocks

函数与main函数

函数是按照顺序执行的语句集合。

每一个C++程序都必须要有一个main函数。一个程序开始执行的时候,开始于main函数中的第一条语句,然后按照顺序执行余下语句。

说到函数,你可能会看到main() 或者 doSomething(),后面的括号其实起了一个说明作用。这个括号就说明他前面的那个字符是一个函数的名字。

分析“hello world”
#include <iostream>
 
int main()
{
   std::cout << "Hello world!"
   return 0;
}
  • 第一行:一个预处理指令。这个预处理器指令指示,我们希望使用iostream库的内容,它是c++标准库的一部分,允许我们从控制台上读写文本。我们需要这一行以便在第5行上使用std::cout。排除这一行将导致第5行出现编译错误,因为编译器不知道std::cout是什么。
  • 第2行是空的,编译器会忽略它。这一行的存在只是为了帮助使程序对人类更具可读性(通过分隔#include预处理指令和程序的后续部分)。
  • 第3行告诉编译器我们要编写(定义)一个名为main的函数。每个c++程序必须有一个主函数,否则它将无法编译。
  • 第4行和第7行告诉编译器哪些行是主函数的一部分。第4行上的左大括号和第7行上的右大括号之间的所有内容都被认为是主函数的一部分。这叫做函数体
  • 第5行是main函数中的第一个语句,也是运行程序时执行的第一个语句。cout(代表“字符输出”)和<<操作符允许我们将字母或数字发送到要输出的控制台。在本例中,我们向它发送文本“Hello world!”,将输出到控制台。此语句创建程序的可见输出。
  • 第6行是一个返回语句。当可执行程序完成运行时,程序将一个值发送回操作系统,以指示它是否成功运行。按照惯例,这个特殊的return语句将0的值返回给操作系统,这意味着“一切正常!”这是执行的程序中的最后一条语句。

结尾,什么是C++ 标准库?

  • 答:一个标准库文件是一个 预编译代码的集合,它被“打包”起来,以供其他程序重用。

1.2 注释

正确的注释

  • At the library, program, or function level, use comments to describe what.
  • Inside the library, program, or function, use comments to describe how.
  • At the statement level, use comments to describe why.

1.3 — Introduction to variables

data:数据

data就是可以被电脑移动、存储、处理的任何信息。

计算机上的数据通常以一种便于存储或处理的格式存储(因此人类无法读懂),这种格式就是:二进制(binary)

Objects and variables:对象和数据

  • RAM(random access memory):随机存取存储器。在程序中,你可以把RAM看作一列邮箱,它可以在程序运行时存储数据。存储在内存中的单个数据,称为value

  • 在C++中,不允许直接访问内存。但可以通过object来访问内存。一旦创建object,编译器就自动的决定这个object存放在内存中的位置。

    object:是具有value和其他相关属性的存储区域。

    这样,我们就可以说,获取这个object的value,编译器直到这个value存储在内存的具体位置。也就是说,我们可以只关注使用object(对象)来存储和检索value,而且不用担心它在内存中的存储位置。

  • object(对象)可以命名也可以不命名。有名字的object叫做:variable(变量)。这个object的名字,叫做:标识符(identifier)

    在一般编程中,对象通常指内存中的变量、数据结构或函数。在c++中,“对象”的定义较窄,将函数排除在外。

Variable instantiation:变量实例化

  • 为了创建一个变量,需要用一种特殊的声明:定义

    int x; // define a variable named x, of type int
    
    1. 在编译时,当编译器看到这个语句,它会告诉自己我们需要定义一个变量,变量名字叫x,类型为int。从此之后,只要编译器看到标识符x,它就知道我们在引用这个变量。

    2. 程序运行时(称为:runtime),该变量将会被**实例化**。变量在用来存储values之前,必须要先实例化。

      实例化:对象(object)将会被创建,并且会分配一个内存地址。

      为了便于举例,假设变量x是在内存位置140处实例化的。当程序使用变量x时,它将访问内存位置140中的值。实例化的对象有时也称为实例

Data types:数据类型

  • Data types(更通用的称呼:type):它告诉编译器变量将会存储什么类型的value

在c++中,变量的类型必须在编译时(当程序被编译时)已知,如果不重新编译程序,就不能更改该类型。这意味着一个整型变量只能包含整型值。如果希望存储其他类型的值,则需要使用不同的变量。

Summary

  1. Data is any sequence of symbols (numbers, letters, etc…) that can be interpreted to mean something.
  2. A value is a single piece of data stored in memory.【值是存储在内存中的单个数据块。】
  3. A variable is a named region of memory.【变量是一个命名的内存区域。】
  4. An identifier is the name that a variable is accessed by.【标识符是变量被访问的名称】
  5. A type tells the program how to interpret a value in memory.【类型是告诉程序如何解释内存中的值】

1.4 变量赋值与初始化

定义变量

int x; // define an integer variable named x
int y, z; // define two integer variables, named y and z

变量赋值:

int width; // define an integer variable named width
width = 5; // copy assignment of value 5 into variable width

初始化变量:(定义&赋值同时进行)

int a = 1; //初始化变量a为1

C++初始化变量的形式有三种:

  1. 使用**“=”** copy initialization

    int width = 5; // copy initialization of value 5 into variable width
    
  2. 使用括号**“()”** direct initialization 【这种在一些高级数据类型上,性能较好】

    int width(5); // direct brace initialization of value 5 into variable width (preferred)
    
  3. 使用大括号**“{}”** Brace initialization(uniform initialization)[推荐这种]

    这种可以用于对象初始化一系列的数据

    /*推荐第一种形式*/
    int width{ 5 }; // direct brace initialization of value 5 into variable width (preferred)
    int height = { 6 }; // copy brace initialization of value 6 into variable height
    

    另外,空初始化:用空的花括号对数据进行Zero initialization。它表示对该变量初始化为0,或者为空。

    int width{}; //zero initialization to value 0
    

对于上述三种初始化方法,看一下下面的例子:

#include <iostream>
using namespace std;

int main()
{
    int a = 1.2;
    int b(2.8);
    int c{ 3.1 };
    cout << a << b << c << endl;
    
    cin.clear();
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
    cin.get();
}

运行结果:

第三种初始化方法更严谨

从运行结果可以看出,第1和2种方法只会基于**“警告”,它们运行结果就是只把整数部分初始化给响应变量;而第三种就直接提示“出错”**。


变量初始化是很有必要的。如果不初始化,编译器可能报错的ヾ(≧O≦)〃嗷~

1.5介绍输入输出流:cout cin endl

  1. std::endl 与 '\n’

    使用’\n’的效率比std::endl高。因为:

  • std::endl做两件事:1、将光标一刀下一行;2、它“刷新”输出(确保它立即显示在屏幕上)
  • **’\n’**只做一件事:1、将光标一刀下一行;
  1. << 、>>

    <<: insertion operator (<<)

    >>: extraction operator (>>)

1.6 未初始化&未定义

  1. 初始化、赋值、未初始化:

    不像其他语言,C/C++在定义的时候,不会自动的给变量赋值(比如说 0)。所以说,如果一个变量被编译器分配到一个内存地址,如果他没有被人为的赋值,它默认的值就是这个内存地址原来存储的值(也叫“垃圾值”)。

    • Initialization = 在对象被定义的同时给它赋值;
    • Assignment = 在对象被定义之,再赋值给它;
    • Uninitialized = 对象只是被定义,但是还没有被赋值。

    所以,我们应该记住要初始化对象(因为现在,初始化对象的成本与带来的好处相比,成本不值一提)。

    不初始化对象,可能会出现无法预料的错误。

  2. 未初始化行为,可能带来以下症状

    • 程序每次运行都会有不同的结果;
    • 程序每次运行都会出现一个相同的错误结果;
    • 程序结果不稳定:有时结果正确,有时结果是错误的;
    • 程序似乎工作,但是稍后的结果不正确;
    • 程序崩溃;
    • 程序可以在一些编译器上运行,但在其他编译器中不能运行;

1.7 关键字&标识符

关键字:

C++17中的关键字(keywords 或者 reserved words)有84个关键字。

标识符:

变量、函数、类、模块、或任何其他用户自定义项目的 的名字 叫做:标识符。

命名规则:

  1. 标识符名字不能和保留字重名;
  2. 标识符只能由字母、下划线、数字;
  3. 标识符必须以 字母 或 数字 开头(“以下划线开头”的一般都是操作系统的保留字;库,或者是编译器使用的);
  4. C++对大小写敏感,所以wa和WA和Wa和wA互不相同。

1.8 常量&操作符

常量(literal,literal constant):是一个已直接插入源代码的固定值。

常量与变量都有一个value(和一个type)。但是,常量的值不可更改

操作符(Operators):在数学中,操作是一种数学计算,包括0个或多个输入值(称为操作数operands),它们产生一个新值(称为输出值)。要执行的特定操作由一个称为操作符的结构(通常是一个符号或一对符号)表示。

操作符分为三类:

  • 一元操作符(Unary operators):只有一个操作数;
  • 二元操作符(Binary operators):有两个操作数(左边、右边各一个);
  • 三元操作符(Ternary operators):有三个操作数。在C++中只有一个三元操作符。

1.9 表达式

  1. 表达式与语句的区别

    当我们需要程序执行某个操作时,使用语句;当我们需要程序计算有一个值的时候,使用表达式

  2. 表达式、语句、表达式语句?

    int x; //语句不含表达式
    int x=5; //语句包含表达式
    x=5;  //表达式语句
    

总结chapter 1

  • 语句(statement):是一种指令,它通常使程序执行某些操作,语句以分号(semicolon)结尾。

  • 预处理指令(Preprocessor directives):告诉编译器执行一种特殊任务。在本章中,用到的是"#include <iostream>"

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值