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没有关系了。