orginate from http://hi.baidu.com/shirdrn/item/6aa992f2d5198ecc531c26af
本來想研究一下Minix操作系統的源代碼,但是因爲剛剛從Java轉過來,有很多東西感覺不是很熟悉,而且感觸最深刻的就是,曾經學過的那個C語言根本一點沒有掌握,此時此刻C語言基礎完全成爲0了。
在Minix中,遇到一個_PROTOTYPE的定義,其實研究了一下,感覺就是C語言中的預定義,一種我從沒有見過的宏的定義方式(僅僅對我而言)。
我知道的,宏定義可以有兩種方式:一種是不帶參數的宏,一種是帶參數的宏。第一種就不說了,定義常量。第二種雖然比較複雜一些,但是基本上是那些用帶參數的宏名來替換一個帶參數的字符串而已。
現在,遇到的讓我真是大開眼界(對應於Minix源代碼中的include/ansi.h文件):
#ifdef _ANSI
/* Keep everything for ANSI prototypes. */
#define _PROTOTYPE(function, params) function params
#define _ARGS(params) params
#define _VOIDSTAR void *
#define _VOID void
#define _CONST const
#define _VOLATILE volatile
#define _SIZET size_t
#else
/* Throw away the parameters for K&R prototypes. */
#define _PROTOTYPE(function, params) function()
#define _ARGS(params) ()
#define _VOIDSTAR void *
#define _VOID void
#define _CONST
#define _VOLATILE
#define _SIZET int
#endif /* _ANSI */
上面定義了基於兩種標準的C代碼風格,一種就是ANSI C標準,其他的爲另一種,這裏給出的是K&R風格的原型的定義。
再看一下具體是如何使用定義的這個原型的(對應於Minix源代碼中的kernel/main.c文件):
#include "kernel.h"
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <a.out.h>
#include <minix/callnr.h>
#include <minix/com.h>
#include "proc.h"
/* Prototype declarations for PRIVATE functions. */
FORWARD _PROTOTYPE( void announce, (void));
FORWARD _PROTOTYPE( void shutdown, (timer_t *tp));
/*===========================================================================*
* announce *
*===========================================================================*/
PRIVATE void announce(void)
{
/* Display the MINIX startup banner. */
kprintf("MINIX %s.%s."
"Copyright 2006, Vrije Universiteit, Amsterdam, The Netherlands\n",
OS_RELEASE, OS_VERSION);
/* Real mode, or 16/32-bit protected mode? */
kprintf("Executing in %s mode.\n\n",
machine.protected ? "32-bit protected" : "real");
}
這裏,省略了一些無關的代碼。其中,PRIVATE和FORWARD是預定義,定義如下(對應於Minix源代碼中的include/minix/const.h文件):
#define PRIVATE static /* PRIVATE x limits the scope of x */
#define FORWARD static /* some compilers require this to be 'static'*/
他們隱藏了C中的關鍵字static。
這下,上面的代碼就非常容易理解了。其實,就是展開宏以後,就是下面的代碼:
#include "kernel.h"
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <a.out.h>
#include <minix/callnr.h>
#include <minix/com.h>
#include "proc.h"
/* Prototype declarations for PRIVATE functions. */
static _PROTOTYPE( void announce, (void));
static _PROTOTYPE( void shutdown, (timer_t *tp));
/*===========================================================================*
* announce *
*===========================================================================*/
static void announce(void)
{
/* Display the MINIX startup banner. */
kprintf("MINIX %s.%s."
"Copyright 2006, Vrije Universiteit, Amsterdam, The Netherlands\n",
OS_RELEASE, OS_VERSION);
/* Real mode, or 16/32-bit protected mode? */
kprintf("Executing in %s mode.\n\n",
machine.protected ? "32-bit protected" : "real");
}
下面,我們使用這種預處理的定義方式來做個簡單的例子,熟悉一下。
定一個頭文件shitype.h,內容如下:
#define _PROTOTYPE(function, params) function params
這裏,只是使用define定義了一個原型。
測試文件如下所示:
#include <stdio.h>
#include "shitype.h"
_PROTOTYPE( void DisplayYourname, (char* yourname)); // 聲明原型
int main(){
DisplayYourname("Shirdrn");
return 0;
}
void DisplayYourname(char* yourname){
printf("Your name is : %s",yourname);
}
編譯運行結果如下所示:
Your name is : ShirdrnPress any key to continue
其實,聲明一個原型的過程,就是在聲明一個函數。
我們可以不使用聲明,但是需要將函數的定義放到主函數main的前面,如下所示:
#include <stdio.h>
// #include "shitype.h"
// _PROTOTYPE( void DisplayYourname, (char* yourname));
void DisplayYourname(char* yourname){
printf("Your name is : %s",yourname);
}
int main(){
DisplayYourname("Shirdrn");
return 0;
}
編譯運行,結果與上面是一樣的。
如果像上面一樣不進行聲明,就和頭文件shitype.h沒有關係了。