0

可能重复:
C中##预处理器的用途是什么

来自Google TTS 的乐趣……任何人都可以了解这段代码的工作原理吗?特别是 - “c##_”是什么符号?-

#define DsHook(a,b,c) if (!c##_) { 
INT_PTR* p=b+*(INT_PTR**)a;  VirtualProtect(&c##_,4,PAGE_EXECUTE_READWRITE,&no);
*(INT_PTR*)&c##_=*p;  VirtualProtect(p,4,PAGE_EXECUTE_READWRITE,&no);  *p=(INT_PTR)c;

它在代码中展开为 -

//  redirect  7th member func of IAsyncReader (SyncReadAlligned) to grab mp3 data from output pin of source filter
DsHook(reader,6,SyncReadAlligned); 

我想,这不是很安全的记忆方式,但作者评论它“不重要”:

像钩子这样不重要的代码以片段形式折叠,但可以随意展开并以您喜欢的方式格式化代码。

PS 如果 Google 已经阻止了“Fun with Google”本身(如果有人有兴趣测试)。

更新:我认为,简短的分析将是-“重定向 IAsyncReader (SyncReadAlligned) 的第 7 个成员函数以从源过滤器的输出引脚获取 mp3 数据”,我们将已提交页面的某些区域的内存保护从“无论如何是”到 PAGE_EXECUTE_READWRITE(允许完全访问)。

关于安全 MSDN 说 -

最好避免使用 VirtualProtect 更改由 GlobalAlloc、HeapAlloc 或 LocalAlloc 分配的内存块上的页面保护,因为单个页面上可以存在多个内存块。...当保护一个可执行的区域时,调用程序负责确保缓存的一致性...

4

2 回答 2

5

这是一个预处理器指令,意思是“连接”。c##_将产生一个包含参数的替换值c和文字字符的标记_。例子:

#define foo(c) c##_

当使用 调用时foo(bar),这将扩展为bar_.

于 2013-01-15T07:40:20.167 回答
2

该符号##在宏定义中具有特殊含义,即连接。这里c##_将 c 与下划线连接起来形成一个新的记号c_。注意这里 c 是一个参数。因此,通过hereIAm作为参数传递给宏,扩展c##_后将变为hereIAm_.

于 2013-01-15T07:41:52.590 回答