几独难懂的 C 语言宏[还是没有抓明白]

几只难懂的 C 语言宏[或者不曾打出懂]

 

只是变换参数宏

稍许上定义一个宏来代替某个函数 但是是函数是只是更换参数的话语
那即便需要考虑办法了

定义方法如下

CODE

#define PRINT(…) printf(__VA_ARGS__)
#include <stdio.h>
int main(){
PRINT(“%d %s %s”,1,”吃饭了吗 smile MM:)”,”\n”);
return 0;
}

 

宏组合

也就是## 和 #的用法
## 是连接符号 连接少单庞大
#大凡将名字代替成字符串

如下

CODE

#define s5(a) supper_ ## a
#include <stdio.h>
void supper_printf(const char* p )
{
printf(“this is supper printf:\n%s\n”,a);
}

int main()
{
 s5(printf)(“hello owrld”);
 return 0;
}

#因而法如下
#include <stdio.h>
#define s(p) #p
int main(){
printf(s(p)”\n”);
return 0;
}

运作一下即使知了

#pragma once

#ifndef _MALLOC_SAFE_H_
#define _MALLOC_SAFE_H_

#include <stdio.h>
#include <string>

//#define malloc3(size) ( malloc_fast_safe(size, __FILE__,
__FUNCTION__, # __LINE__) )
#define malloc(size) ( malloc2(size, __LINE__) )
#define malloc_line(size, line) ( malloc_fast_safe(size,
__FILE__, __FUNCTION__, #line) )
#define free(buf) ( free_fast_safe(buf) )

//一个简约的高效检测方法
void * malloc_fast_safe(int len, const char * c__FILE__, const
char * c__FUNCTION__, const char * c__LINE__);

void free_fast_safe(void * p);

#endif

还是好,要这么

#pragma once

#ifndef _MALLOC_SAFE_H_
#define _MALLOC_SAFE_H_

#include <stdio.h>
#include <string>

//宏里面变成字符串还是蛮啰嗦,要就此鲜级宏加 “#” 来处理
#define __STRINGIFY__(x) #x
#define __TOSTRING__(x) __STRINGIFY__(x)

//#define malloc(size) ( malloc_fast_safe(size, __FILE__,
__FUNCTION__, #__LINE__) )
#define malloc(size) ( malloc_fast_safe(size, __FILE__,
__FUNCTION__, __TOSTRING__(__LINE__)) )
#define free(buf) ( free_fast_safe(buf) )

//一个简的迅速检测方法
void * malloc_fast_safe(int len, const char * c__FILE__, const
char * c__FUNCTION__, const char * c__LINE__);

void free_fast_safe(void * p);

#endif

参考自 google “__LINE__ 字符串”

http://www.cppblog.com/heath/archive/2008/08/05/58046.html


使用__FILE__和__LINE__定点错误

[前言:使用__FILE__和__LINE__来恒定错误就习以为常,然而其中有的道理又发几乎个人密切推究了。本文参考了Curtis
Krauskopf的一律篇名叫吧Using __FILE__ and __LINE__ to Report
Errors的稿子,希望达到对的效。]

题目:当运行时不当有时,我怎样才能得到包含C++文件称与行号的字符串信息?
回答:在C++中的__FILE__预编译指示器包含了于编译的文书称,而__LINE__虽然带有了自代码的行号。__FILE__和__LINE__的光景都含了一定量独下划线,让咱们精心看看__FILE__所蕴藏的每个字符:

_ _ F I L E _ _

脚展示了当控制台程序中若显示文件名和代码行号。

#include <stdio.h>

int main(int , char**)
{
     printf(“This fake error is in %s on line %d\n”,         __FILE__, __LINE__);
     return 0;
}

输出结果:

This fake error is in c:\temp\test.cpp on line 5

于咱们更上一层楼

自我怀念通过一个通用函数error()来喻错误,以使当有错误产生时自己能够设置断点以及隔离错误处理(例如,在屏幕及打印错误信息或者写副日志)。因此,函数的原型应该是如此的吧:

void error(const char *file, const unsigned long line,
const char *msg); 

调用方式如下:

error(__FILE__, __LINE__, “my error message”);

先期处理魔法

此间有三独问题待缓解:

  1. __FILE__和__LINE__在每次调用error时当参数传入。
  2. __FILE和__LINE__左右的下划线很轻吃忘记,从而致使编译错误。
  3. __LINE__凡一个整数,这的确增加了error函数的复杂度。我不用想直接用整型的__LINE__,而平凡都是将变为字符串打印至屏幕或摹写副日志文件。

__FILE__和__LINE__应当吃自动处理,而未每次作为参数传递给error,这样见面给error的使用者感到还爽些,它的形式可能是下边这样:

error(AT, “my error message”);

 
自身想地方的宏AT展开也:”c:\temp\test.cpp:5″。而新的error函数则成:

void error(const char *location, const char *msg);

 

坐Borland C++
Builder编译器能够活动合并相邻之字符串,因此我管AT写成下面这样:

#define AT __FILE__ “:” __LINE__ 

但是它们也罢工了,因为__LINE__吃扩大成了整数而非字符串,所以宏展开后成为:

“c:\temp\test.cpp” “:” 5

随即是一个不行的字符串,因为最后有一个勿给夹引号包含的平头。

岂处置?别着急,一个异的预编译指示器“#”能够帮忙我们拿一个变量转换成字符串。所以重复定义宏:

#define AT __FILE__ “:” #__LINE__

嘿嘿,这样总行了吧。别高兴得太早,这样也是不行的。因为编译器会抱怨#是个无效字符。其实,问题是#预编译指示器只有这样使用才会
被正确识别:

#define symbol(X) #X 

据此,我将代码改吧:

#define STRINGIFY(x) #x
#define AT __FILE__ “:” STRINGIFY(__LINE__) 

但,奇怪之结果发生了,__LINE__还是叫当做了出口的一律有:

c:\temp\test.cpp:__LINE__: fake error

解决智是更就此一个宏来包装STRINGIFY():

#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define AT __FILE__ “:” TOSTRING(__LINE__)

OK,我们因此脚的代码来尝试:

#include <stdio.h>
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define AT __FILE__ “:” TOSTRING(__LINE__)
void error(const char *location, const char *msg)
{
  printf(“Error at %s: %s\n”, location, msg);
}
int main(int , char**)
{
  error(AT, “fake error”);
  return 0;
}

出口结果:

Error at
c:\temp\test\test.cpp:11: fake error

Visual Studio下的尽
每当《Windows核心编程》中,Jeffrey
Richter提供了下面的宏在编译期输出有因此信息:

#define chSTR2(x) #x
#define chSTR(x)  chSTR2(x)
#define chMSG(desc) message(__FILE__ “(” chSTR(__LINE__) “):” #desc)

message是一个预编译指令,上面宏的运用方法是:

图片 1#pragma chMSG(Fix this later)

结论

  1. 预编译指示器__FILE__和__LINE__会提供行之有效的音信。
  2. __LINE__的处理方式远较我们想象的假设复杂。
  3. __FILE__叫拍卖成字符串,给咱们带来了好多利。

posted on 2008-08-05 11:55