令人迷糊的define和typedef

來源:互聯網
上載者:User

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
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.