C/C++ 预定义宏

一、__GNUC__  / __GNUG__

    1 __GNUC__  / __GNUG__是gcc / g++编译器编译代码时预定义的一个宏。需要针对gcc / g++编写代码时, 可以使用该宏进行条件编译。

    2 __GNUC__  / __GNUG__的值表示gcc / g++的版本。需要针对gcc / g++特定版本编写代码时,也可以使用该宏进行条件编译。

    3 __GNUC__  / __GNUG__的类型是“int”,该宏被扩展后, 得到的是整数字面值。可以通过仅预处理,查看宏扩展后的文本。

#include <assert.h>
#include <stdio.h>
#include <typeinfo>
#ifndef __GNUC__
   /* error sample for gcc compiler */
#elif __GNUG__
   /* error sample for gcc compiler */
#else
   /* use gcc special extension: #warning , __attribute__, etc.  */
#endif

int main() 
{
  printf("hello gcc %d\n",__GNUC__);    
  assert( typeid(__GNUC__)==typeid(int) );    
  printf("press Enter to exit\n");    
   (void)getchar();
   return 0;
}

 

二、_MSC_VER

    1 _MSC_VER是微软C/C++编译器——cl.exe编译代码时预定义的一个宏。需要针对cl编写代码时, 可以使用该宏进行条件编译。

    2 _MSC_VER的值表示cl的版本。需要针对cl特定版本编写代码时, 也可以使用该宏进行条件编译。

    3 _MSC_VER的类型是"int"。该宏被扩展后,得到的是整数字面值。可以通过仅预处理, 查看宏扩展后的文本。

/* _MSC_VER\_MSC_VER.cpp */
#include <stdio.h>
#include <stdlib.h>
#include <typeinfo>

#define TO_LITERAL(text) TO_LITERAL_(text)
#define TO_LITERAL_(text) #text

#ifndef _MSC_VER
   #error sample for msvc compiler
#else
    /* use msvc special extension: #pragma message,__declspec,__stdcall,etc. */
    #pragma message("----------------------------------------\n")
    #pragma message("----------------------------------------\n")
    #pragma message("---------- hello msvc " TO_LITERAL(_MSC_VER) " -------------")
    #pragma message("\n----------------------------------------\n")
    #pragma message("----------------------------------------\n")
    extern __declspec(dllimport) void __stdcall declare_but_dont_reference(void);
#endif
    
int main()
{    
  printf("hello msvc, version=%d\n",_MSC_VER);    
  printf("typeof _MSC_VER=\"%s\"\n",typeid(_MSC_VER).name());    
  system("pause"); /* msvc only on windows? */    
  return 0;
}

 

三、__FILE__,__LINE__,__FUNCTION__(或__func__)

__FILE__:当前程序行所在源文件名称,标准C支持,该宏当做字符串对待; 
__LINE__:当前程序行所在源文件内的行号,标准C支持,该宏当做整形对待; 
__FUNCTION__(或__func__):当前程序行所属的函数名称,C99支持(如:VC++6.0不支持),该宏当做字符串对待;

#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
    printf("[%s:%d]%s|%s\n", __FILE__, __LINE__, __FUNCTION__, __func__);
    return 0;
}

执行上述程序将打印: 

[test.cpp:8]main|main

 

四、__DATE__,__TIME__

__DATE__:当前文件的编译日期,格式是Mmm:dd:yyyy。该宏当做字符串对待。 
__TIME__:当前文件的编译时间,格式是hh:mm:ss。该宏当做字符串对待。

#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
    printf("DATE:%s|TIME:%s\n", __DATE__, __TIME__);
    getchar();
    return 0;
}

 执行上述程序将打印:

DATE:Oct 20 2010|TIME:23:33:24

 

五、"#"和"##"使用方法

1 "#":替换宏参数时,将其后面的宏参数转换成带引号的字符串,例如:

#define STR(s)  #s
int main( )
{
    std::string str = STR(abcdefg);
    return 0;
}

C编译器在预处理代码时,第5行实际翻译成:std::string str = "abcdefg"; 

2 "##":将该符号前后的两个宏参数连接在一起,比如:

#define PRINT(PRINT_FUNNAME, VAR) print_##PRINT_FUNNAME(VAR)
int main()
{
    PRINT(common, 5);
    return 0;
}

C编译器在预处理代码时,第5行实际翻译成:print_common(5); 

我们实际看下综合运用的例子:

#include <iostream>
using namespace std;

#define PRINT(fun, name, var) print_##fun(#name, var)

void print_common(const std::string & name, int var)
{
	std::cout << name.c_str() << ":" << var << std::endl;
}

void print_tofile(const std::string & name, int var)
{
	char sz_temp[1024];
	memset(sz_temp, 0, sizeof(sz_temp));
	snprintf(sz_temp, sizeof(sz_temp), "%s:%d", name.c_str(), var);
	FILE * fp = fopen("./log.log", "w");
	fwrite(sz_temp, 1, strlen(sz_temp), fp);
	fclose(fp);
}

int main()
{
	PRINT(common, age, 5);
	PRINT(tofile, age, 5);
	return 0;
}

 

转载于:https://my.oschina.net/shou1156226/blog/754543

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值