C标准中的一些预定义宏对调试程序有很大帮助

来源:互联网 发布:百度网站排名优化 编辑:程序博客网 时间:2024/06/05 19:06

预处理命令#pragma和预定义宏

一、C预定义宏
C标准指定了一些预定义宏,编程中常常用到。
__DATE__     进行预处理的日期
__FILE__     代表当前源代码文件名的字符串
__LINE__     代表当前源代码文件中行号的整数常量
__STDC__     设置为1,表示该实现遵循C标准
__STDC_HOSTED__  为本机环境设置为,否则设为0
__STDC_VERSION__ C99时设置为199901L
__TIME__     源文件的编译时间
__func__     C99提供的,为所在函数名的字符串
对于__FILE__,__LINE__,__func__这样的宏,在调试程序时是很有用的,

因为你可以很容易的知道程序运行到了哪个文件的那一行,是哪个函数.

例如:
#include
#include
void why_me();
int main()
{
    printf( "The file is %s\n", __FILE__ );
    printf( "The date is %s\n", __DATE__ );
    printf( "The time is %s\n", __TIME__ );
    printf("The version is %s\n",__STDC__VERSION__);
    printf( "This is line %d\n", __LINE__ );
    printf( "This function is %s\n ", __func__ );
   why_me();
   return 0;
}
void why_me()
{
    printf( "This function is %s\n", __func__ );
    printf( "This is line %d\n", __LINE__ );
}

二、#line#error
#line用于重置由__LINE____FILE__宏指定的行号和文件名。
用法如下:#line number filename
例如:#line 1000 //将当前行号设置为1000
     #line 1000 "lukas.c"   //行号设置为1000,文件名设置为lukas.c

#error指令使预处理器发出一条错误消息,该消息包含指令中的文本.这条指令的目的就是在程序崩溃之前能够给出一定的信息。

三、#pragma
在所有的预处理指令中,#Pragma 指令可能是最复杂的了。#pragma的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。#pragma指令对每个编译器给出了一个方法,在保持与CC++语言完全兼容的情况下,给出主机或操作系统专有的特征。依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的。
其格式一般为: #Pragma Para
其中Para 为参数,下面来看一些常用的参数。

(1)message 参数。 Message 参数是我最喜欢的一个参数,它能够在编译信息输出窗口中输出相应的信息,这对于源代码信息的控制是非常重要的。其使用方法为:
#Pragma message(“消息文本”)
当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。
当我们在程序中定义了许多宏来控制源代码版本的时候,我们自己有可能都会忘记有没有正确的设置这些宏,此时我们可以用这条指令在编译的时候就进行检查。假设我们希望判断自己有没有在源代码的什么地方定义了_X86这个宏可以用下面的方法
#ifdef _X86
#Pragma message(“_X86 macro activated!”)
#endif
当我们定义了_X86这个宏以后,应用程序在编译时就会在编译输出窗口里显示“_
X86 macro activated!”。我们就不会因为不记得自己定义的一些特定的宏而抓耳挠腮了。

(2)另一个使用得比较多的pragma参数是code_seg。格式如:
#pragma code_seg( ["section-name"[,"section-class"] ] )
它能够设置程序中函数代码存放的代码段,当我们开发驱动程序的时候就会使用到它。

(3)#pragma once 
只要在头文件的最开始加入这条指令就能够保证头文件被编译一次。

(4)#pragma hdrstop表示预编译头文件到此为止,后面的头文件不进行预编译。BCB可以预编译头文件以加快链接的速度,但如果所有头文件都进行预编译又可能占太多磁盘空间,所以使用这个选项排除一些头文件。
有时单元之间有依赖关系,比如单元A依赖单元B,所以单元B要先于单元A编译。你可以用#pragma startup指定编译优先级,如果使用了#pragma package(smart_init) BCB就会根据优先级的大小先后编译。

(5)#pragma warning( disable : 4507 34; once : 4385; error : 164 )等价于:
#pragma warning(disable:4507 34) /* 不显示450734号警告信息。如果编译时总是出现4507号警告和34号警告,
                                    而认为肯定不会有错误,可以使用这条指令。*/
#pragma warning(once:4385) // 4385号警告信息仅报告一次
#pragma warning(error:164) // 164号警告信息作为一个错误。
同时这个pragma warning 也支持如下格式:
#pragma warning( push [ ,n ] )
#pragma warning( pop )
这里n代表一个警告等级(1---4)
#pragma warning( push )保存所有警告信息的现有的警告状态。
#pragma warning( push, n)保存所有警告信息的现有的警告状态,并且把全局警告等级设定为n
#pragma warning( pop )向栈中弹出最后一个警告信息,在入栈和出栈之间所作的一切改动取消。例如:
#pragma warning( push )
#pragma warning( disable : 4705 )
#pragma warning( disable : 4706 )
#pragma warning( disable : 4707 )
//.......
#pragma warning( pop )
在这段代码的最后,重新保存所有的警告信息(包括470547064707)

在你写dll的时候,因为对于CC++,编译器会有不同的名字解析规则,所以可以这样用

#ifndef   __STDC__

extern "C "   void   function();

#else

void   function();

#endif

 

 __LINE__           在源代码中插入当前源代码行号
  __FILE__           在源代码中插入当前源代码文件名
  __DATE__           在源代码中插入当前编译日期〔注意和当前系统日期区别开来〕
  __TIME__           在源代码中插入当前编译时间〔注意和当前系统时间区别开来〕  
  __STDC__           当要求程序严格遵循ANSIC标准时该标识符被赋值为1
----------------------------------------------------------------------------

标识符__LINE____FILE__通常用来调试程序;标识符__DATE____TIME__通常用来在编译后的程序中加入一个时间标志,

以区分程序的不同版本;当要求程序严格遵循ANSIC标准时,标识符__STDC__就会被赋值为1;当用C++编译程序编译时,标识符__cplusplus就会被定义。

#include

 

int main ()

{

    printf("该输出行在源程序中的位置:%d\n", __LINE__ );

    printf("该程序的文件名为:%s\n", __FILE__ );

    printf("当前日期为:%s\n", __DATE__ );

    printf("当前时间为:%s\n", __TIME__ );

 

    return 0;

}
 

#include

void main(void)

{

    int flag=1

    printf("%d",__LINE__); // Line 6

}

结果为:6

#include "stdafx.h"

#include

void main(void)

{
 
    printf("%d",__LINE__); // Line 5

}