预处理&&const&&sizeof

March 14, 2015

Reading time ~1 minute

分享一下预处理&&const&&sizeof里一些小技巧

define的用法

1.用define声明一月有多少秒

一开始很想这么写,感觉就是声明个常量。

#define SECONDS_JANUARY 2678400

而下面的写法就明显好的多。

#define SECONDS_JANUARY 60*60*24*31

这样的宏可以让计算表达式表现出程序员的意图和计算的方式。

2.用define声明标准的宏MIN

#define MIN(A,B) ((A)<=(B))?(A):(B)

这里其实主要就是考察一下三重条件操作符,记得一定要括括号,这最好变成习惯,不然会引发如下错误。

#define MUL(A,B) A*B
int main()
{
	int a = MUL(3+5,8) //希望的是(3+5)*8,最后得到3+5*8
}

const的用法

四个const区分

int b = 10;
const int *a = &b; //case 1
int const* a = &b; //case 2
int* const a = &b; //case 3
const int* const a = &b;//case 4

首先case 1 和 case 2是完全等价的。 如果const在星号左侧,const修饰的就是所指向的变量,如果const在星号右侧,修饰的就是指针本身。 所以如果是case1和case2的话,我们就不能修改指向的变量.

所以在case 1,case 2 下面的语句都是违法的.

*a = 600;//不能修改

但如果要修改指针a指向的值得,以下语句可以代替达到这种效果。

int b = 500;
const int* a = &b;
b = 30;//方法1 修改指向的内容
int c = 30;
a = &c; //方法2 指向新的内容

那如果是case3的话,也就是const在星号的右侧,说明指针本身是一个常亮。 那么就不能对指针本身做任何操作。例如以下的行为。

int b = 50 , c = 20;
int* const a;//错误 必须初始化,不然就永远指向未知。
int* const a = &b; //正确,初始化
*a = 500 ; //正确,可以修改
cout << a++ << endl ;//错误,不能对a做指针操作

而case 4也很明显就是既不能修改值,也不能修改指针。

为什么要用const成员函数呢?

因为一些成员函数是不需要改变类中的数据成员的,它们是只读函数。所以如果加上const标示可以提高程序的可读性,也可以防止这些函数企图修改数据成员的值,让编译器报错。

让我们来看看以下两个const函数写法:

int Point::GETY() const
{
	return yVAL;
}
//这个意思是const的成员函数,即函数不能修改数据成员。
const int Point::GETY()
{
	return yVAL;
}
//说明返回的值是一个const int.

那么问题来了,#define和const 都能修饰常量,哪种更好?

  • const常量有数据类型,而define没有,编译器可以对前者做类型检查,而后者只是字符替换,所以可能会在替换中产生未知的bug(边际效应)
  • 有些集成化的调试工具会调试const常量,却无法调试宏