因为找工作的缘故,从头仔仔细细的学习一遍C++,有什么错误或者不足的地方还望各位大佬指出,共同学习,共同进步。学习的书籍是《C++Primer》
预处理器指示符
首先是include,头文件通过include指示符成为程序的一部分,预处理指示符用“#”来标识。
#include有两种格式:
第一种是#include<stdio.h>,文件名用<>括起来,表示是从系统给的库内去检索头文件。
第二种是#include"wyl.h",这种形式表示该文件是用户提供的头文件,查找该文件时将从当前文件目录开始查找。
#include的本质其实就是把所调用的头文件内容拷贝过来。
那么问题来了,当我们在运行一个CPP文件的时候,在开头会加上各种头文件的调用,当调用的头文件中含有#include指示符时(即一个头文件可能会被多次包含在一个源文件中),会造成头文件的重复处理,会造成时间和空间上的浪费,这时候怎么办呢?
如上图出现的这种情况,wyl.h这个头文件会被多次调用,会多次拷贝在源文件中会造成空间的浪费和代码运行时间的增加。
ifndef
针对以上情况我们引入条件指示符#ifndef
我们用如下代码就可以防止头文件被重复处理:
#ifndef BOOK
#define BOOK
/*代码段*/
#endif
那么这段代码有什么用呢?我们来逐行解释
首先第一行,由条件指示符和一个预编译器常量组成(预编译器常量可以理解为一个标识,独属于这个头文件的标识,习惯上常常用大写字母来表示)。那么第一段的作用就是:检查BOOK在前面有没有被定义,如果被定义则#ifndef指示符的值为假,它与#endif指示符之间的行将被忽略,如果没用被定义,则#ifndef的值为真,#ifndef和#endif之间的所有语句都被包含进来进行处理。
第二行是由宏定义指令和预编译器常量组成作用就是定义BOOK,保证头文件只被处理一次。把他放在#ifndef后面,头文件的内容第一次被处理时,BOOK就被定义,从而防止在之后的调用时#ifndef的值为真。
ifdef
#ifdef指示符常被用来判断一个预处理常量已被定义,一遍有条件地包含程序代码。如例:
#include<stdio.h>
int main()
{
#ifdef BOOK
printf("hello");
#endif
printf("hi");
return 0;
}
在上述代码中如果没有定义BOOK,编译后代码段实际上相当于
#include<stdio.h>
int main()
{
printf("hi");
return 0;
}
如果定义BOOK编译后相当于实现下列代码
#include<stdio.h>
int main()
{
printf("hello");
printf("hi");
return 0;
}
在编译过程中我们也可以用#ifdef来辨别程序属于C语言还是C++语言。
在编写c++程序时,编译器自动定义了一个预处理器名字__cplusplus(前后两个下划线)
在编写c程序时编译器自动定义名字STDC
(书上是这么说的,亲测两次不对,用vs2012和vs2017都试过,都跳过了,_DEBUG亲测可以)
这两个不会被同时定义,可以用来辨别是C++还是C程序。
同时呢还有几个有用的预定义名字:LINE、FILE、TIME和DATA(前后都有双下划线,因为编译原因无法显示)
LINE记录文件已被编译的行数,FILE包含正在被编译的文件的名字,TIME包含编译的时间,DATE包含编译的日期。
#include<iostream>
using namespace std;
int main()
{
for (int i = 0;i < 10;i++)
{
cout << i ;
cout << "\t";
cout << "LINE:" << __LINE__ << "FILE:" << __FILE__;
cout << endl;
}
cout << "time:" << __TIME__ << "date:" << __DATE__ << endl;
getchar();
return 0;
}
运行结果为
**
assert断言
**
头文件:#include<assert.h>,#include< cassert >
形式:assert(表达式)
表达式即为前提条件,如果表达式为假断言失败程序输出诊断消息,然后终止。