`
lovnet
  • 浏览: 6704815 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

令人迷糊的define和typedef

 
阅读更多

1.刚接触MFC时会看到很多陌生的数据类型,关键字.一开始会特别反感,不适应.比如UINT,DWORD.不过你右击一点它们选择跳转到定义.就会发现有这样的定义:

typedef unsigned int UINT;typedef unsigned long DWORD;

另外还有一些宏比如ON_COMMAND,跳转到定义是这样的:

#define ON_COMMAND(id, memberFxn) \
{ WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)id, AfxSigCmd_v, \
static_cast<AFX_PMSG> (memberFxn) },

2.另外有时在一个类的定义之前会发现这样的语句:

#ifndef _MAINFRM_H
#define _MAINFRM_H

下面我们就来分析下typedef和define的用法:

一.typedef用来定义类型别名,define用来替换

typedef应该是typedefine的缩写.顾名思义就是类型定义.于是我们可以把它理解为重新定义一个新类型.只不过是基于原有的类型.另外也可以理解为某个类型的别名.这有点像Oracle中的同义词.比如上面提到的UINT,我们可以认为它是一个新的类型,和类型unsigned int一样.这样我们定义一个非负整数时有两种等价的方式了:

unsigned int num;或UINT num;它们可以互相替换.UINT用起来自然方便一点,简洁一点.但凡事有利有弊.新添加个UINT我们又得花时间去熟悉它记住它.

define就仅涉及到替换某一段字符,不涉及到类型.

举个例子:

#include<iostream>

typedef int INT; //注意typedef不能用来替换一般的字符.比如typedef 123 N;是错误的

#define N 123

#define out(x) std::cout<<x

void main()

{

INT num = N; //等同于int num = N;

char* str = "hello world";

out(str); //输出hello world

out(num); //输出123

}

但是虽然define是仅替换,但如果替换的字符恰巧是类型定义的关键字,那就跟typedef差不多了.比如#define UINT int 和typedef int UINT;达到的效果一样.但是只是效果一样,但意义不一样的.比如这种情况

typedef int* int_ptr1;

#define int_ptr2 int*

int_ptr1 a,b; //a和b都是int*类型的指针

int_ptr2 c,d; //c是int*类型的指针.而d就是int了

这看起来有点晕乎的啊.不过不用去管它们的区别.只要你在涉及到类型的地方用typedef,只涉及到替换的情况用#define好了.这样就不用管这样的烦心事了啊

补充:明白了typedef 和#define的区别后但用有时可能会把他们混淆,分不清谁是谁了.我们可以这样来记忆.

1.typedef里面有个type那肯定是和类型有关的.另外我们平时定义一个类型时会在后面加个分号;所以用typedef时也记得在后面加个分号

2.#define里面有个fine,那就是好.好在哪里呢.符合思维习惯.我们平时定义某个东东时习惯这样的顺序,比如你是个王八蛋.你在前面,定义你的词在后面.#define也是这样.

比如#define 你 "是个王八蛋" 那么你就代表着王八蛋.另外#define定义后面不用分号(你运行它会成功的,平时我们都习惯用英语字母做标识符,其实用汉字也一样可以用来

做变量名函数名的,只不过会有些警告)

而typedef不好,它倒过来了.比如typedef int INT;//INT代表int但它跑后面去了,而不是typedef INT int;

二.define保证头文件被编译一次

假如有三个头文件one.h ,two.h, three.h

在two.h中有include "one.h"

在three.h中有include "one.h" include "two.h"

编译three.h的时候先编译one.h,然后编译two.h,由于two.h里面引用了one.h这里one.h又会被重复编译一次.这样就会出错,说类类型重复定义

我们在one.h中这样写就可以防止这种错误

#ifndef _one_h //_one_h这名字是随便取的,只要别重复,并且跟#define中的一样就行了.

#define _one_h

//#pragma once //这是我注释掉的.在VS中你创建一个类时它自动给你添加它.实现的功能和#define一样.防止重复编译

//不过#pragma是编译器相关的.如果你不用vs用其他的有可能会出错.所以最好还是用#define.它是通用的.

class one

{

one(void);

~one(void);

};

#endif

三.用#define做一些条件判断

我们在程序运行时去动态的做一些判断,符合某些条件哪些代码执行,不符合就不执行.例如是debug还是release,是32位的平台还是64位的平台.我们可以用#define来做判断

举例:

#include "stdafx.h"
#include <iostream>
using namespace std;
void main()
{
#ifdef _WIN32 //也可以这样写#if defined(_WIN32),等价的
cout<<"your computer is 32-bit"<<endl;
#else
cout<<"your computer is 64-bit"<<endl; //我的是64位的,所以执行这段代码
#endif
}

其中的_WIN32是编译器里早定义好的.比如你在VS里工具栏里选了Win32那么默认就#define _WIN32了.如果选x64就对应_WIN64,选Debug对应_DEBUG

当然你也可以自己定义.

#include "stdafx.h"
#include <iostream>
using namespace std;

#define SELECT
void main()
{

#ifdef SELECT
cout<<"part one are running"<<endl; //执行这一段代码
#else
cout<<"part tow are running"<<endl; //如果注释掉#define SELECT则执行这一段
#endif
}

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics