#define,typedef和using用法区别
一.#define
#define 是宏定义命令,主要用于宏替换,是预编译命令,因此会在预编译阶段被执行。
1.无参宏定义(不带参数)
一般形式为:#define 标识符 字符串
以“#”开头的均为预处理命令,“define”为宏定义命令。“标识符”为所定义的宏名。“字符串”可以是常数、表达式、格式串等。
使用如:#define str "13"
2.有参宏定义(宏带参数)
一般形式为:#define 宏名(形参表) 字符串 宏名(形参表) 之间不能有空格
宏定义中的参数称为形式参数,在宏调用中的参数称为实际参数,在调用中,不仅要宏展开,而且要用实参去代换形参。
注意:#define定义一些简单的函数,但因为只是简单的替换,有时后会发生一些错误,谨慎(不建议)使用,在替换列表中的各个参数最好使用圆括号括起来
使用如:
#define add(x,y) (x+y) //此处要打括号,不然执行2*add(x,y) 会变成 2*x + y
int main()
{
std::cout << add(1,1) << std::endl;//输出2
return 0;
}
这个“函数”定义了加法,但是该“函数”没有类型检查,有点类似模板,但没有模板安全,可以看做一个简单的模板。
3.宏定义中的条件编译
这里的#ifndef #define #endif 其实和#pragma once 作用类似防止多次编译一个头文件
#ifndef DATATYPE_H
#define DATATYPE_H
#endif
4.跨平台编译
#ifdef WINDOWS
......
(#else)
......
#endif
#ifdef LINUX
......
(#else)
......
#endif
可以在编译的时候通过#define设置编译环境。
5.特殊操作宏
特殊操作符有#,## 和 … and __VA_ARGS__
(1)#
在c语言中,#的功能时将其后面的宏参数进行字符串化操作,简单说就是在对它所引用的宏变量通过替换后在其左右各加上一个双引号(把传递过来的参数当成字符串进行替代)
使用如:#define C(x) #x 则C(1+1)变成”1+1“
(2)##
功能时在带参数的宏定义中将两个子串连接起来形成一个新的子串。
使用如:#define LINK(a,b,c) a##_b##_c 则LINK(1,2,3) 展开为"1_2_3"
(3)...和__VA_ARGS__
C99规范中新增的,目前似乎只有gcc支持,思想就是宏定义中参数列表的最后一个参数为省略号(也就是三个点)。这样预定义宏__VA_ARGS__就可以被用在替换部分中,替换省略号所代表的字符串
如:
#define PR(...) printf(__VA_ARGS__)
int main()
{
int wt=1,sp=2;
PR("hello\n"); //输出:hello
PR("weight = %d, shipping = %d",wt,sp); //输出:weight = 1, shipping = 2
return 0;
}
(4)其他系统宏
__FILE__ 宏在预编译时会替换成当前的源文件cpp名
__LINE__宏在预编译时会替换成当前的行号
__FUNCTION__宏在预编译时会替换成当前的函数名称
__DATE__:进行预处理的日期(“Mmm dd yyyy”形式的字符串文字)
__TIME__:源文件编译时间,格式微“hh:mm:ss”
二、typedef
typedef <类型> <别名>;
1、简单内置类型别名
typedef unsigned int Uint;
//a,b类型相同
usigned int a;
Uint b;
2、复合类型的别名
//两种方式效果一样
typedef int* p;
typedef int *p;
//下面两种方式等价,但对于代码的理解方便程度不同。a为一个指向整型的指针,b为一个整型。
int* a, b;
int *a,b;
//下面这一种方式则不存在上述问题,a、b的类型均是指向整型的指针
p a,b;
3、自定义类型的别名
//结构体、类、数组、链表、树等别名
//结构体
typedef struct{int x; int y;} Point;
typedef srtruct point{int x; int y;} Point;
//类
typedef class{private: int x; public: int y;} MyClass
//数组
typedef int MyArray [10];//别名是放在中间
MyArray nums;//等价于 int nums[10];
4、函数指针的别名
typedef <return_type> (*<Aliases>)([<para1_type>],[<para2_type>],...)
bool LengthCopmare(const int &, const int &);
typedef (*pf)(const int &, const int &);
pf = LengthCopmare;//可以使用pf调用函数LengthCopmare
pf = &LengthCopmare;//等价
三、using
1.声明命名空间
using namespace std;
2.给类型取别名, 在C++11中提出了通过using指定别名例如:
using 别名 = 原先类型;
using ty= unsigned char;
以后使用ty value; 就代表 unsigned char value;