C++追根究底(持续更新)
头文件
" " 与 <>的区别
<>先去系统目录中找头文件,如果没有在到当前目录下找。所以像标准的头文件 stdio.h、stdlib.h等用这个方法。
""首先在当前目录下寻找,如果找不到,再到系统目录中寻找。 这个用于include自定义的头文件,让系统优先使用当前目录中定义的。
带 .h 和不带 .h 的区别
c++标准化之前的头文件就是带后缀名的文件,标准化后的头文件就是不带后缀名的文件。c++ 98 规定用户应使用新版头文件,对旧版本头文件不在进行强制规范,但大多数编译器厂商依然提供旧版本头文件,以求向下兼容。
c++标准化增加了名称空间概念,借以将原来声明在全局空间下的标识符声明在了namespace std下。使用新版头文件(如#include
带 c前缀 和不带 c前缀 的区别
为了和c语言兼容,c++标准化过程中,原有c语言头文件标准化后头文件名前带个c字母,如cstdio、cstring、ctime、ctype等等。这些头文件都可以在系统目录下(如c:\program files (x86)\microsoft visual studio 14.0\vc\include)找到。
如果要用c++标准化了的c语言头文件,就得作如下的转换:
#include <stdio.h> --> #include <cstdio> #include <stdlib.h> --> #include <cstdlib> #include <string.h> --> #include <cstring>
宏定义
#define命令是c语言中的一个宏定义命令,它用来将一个标识符定义为一个字符串,该标识符被称为宏名,被定义的字符串称为替换文本。
该命令有两种格式:一种是简单的宏定义,另一种是带参数的宏定义。
- 简单的宏定义:
#define <宏名> <字符串>
例: #define pi 3.1415926
- 带参数的宏定义
#define <宏名> (<参数表>) <宏体>
例: #define a(x) x
一个标识符被宏定义后,该标识符便是一个宏名。在该程序被编译前,先将宏名用被定义的字符串替换,这称为宏替换,替换后才进行编译,宏替换是简单的替换。
特殊符号:#,##,#@
- #x:给x加双引号
#define tostring(x) #x //str="123132"; char* str = tostring(123132);
- x##y:表示x连接y
#define conn(x,y) x##y //n=123456; int n = conn(123,456);
- #@x:给x加上单引号
#define tochar(x) #@x //a='1'; char a = tochar(1); //报错 char a = tochar(123);
防止一个头文件被重复包含
#ifndef bodydef_h #define bodydef_h //头文件内容 #endif
do-while 作用
do-while 语句的一个特点便是,会优先执行一次语句块,而后再判断 while 中的条件是否成立。当我们把 while 设置为 while(0) 时,那么 while 条件永不成立,do 后面语句块中的代码只会执行一次。
宏定义的多行代码用 do { /* ... */ } while(0) 包围起来可以减少歧义:
#include <stdio.h> #define macro_func() \ do \ { \ printf("hello\n"); \ printf("world\n"); \ } while(0) /* 根据上面例子的描述,我们不应该在宏定义末尾添加分号 */ int main() { if(2 > 1) macro_func(); else printf("fail.\n"); return 0; }
假设没有用do-while或只使用{},后面的else部分必然会报错。
注:宏定义函数编写时需要换行时,需要使用续行符——反斜杠 ''。
undef 的用法
当用完一个宏,不希望下面的代码再用到这个宏,,那么就可以#undef它。下面如果再用到这个宏,编译器就会报错。常用做法为:
#define max 50 #include "common.h" #undef max
这样就只有在common.h中才能使用宏max。
函数外部加括号
部分函数在使用时需要用括号括起来,如:
cout << (numeric_limits<int>::min)() << endl;
因为microsoft在 windef.h 中定义了两个宏 max 和 min,函数名和宏同名时,要么 #undef ,要么用小括号括起来。