__CLASS__
C++中是否有一个宏,它给出类似于__FUNCTION__
宏的类名,它给出了函数名
在gatomic.c
glib 中,有几个函数声明如下所示:
gboolean
(g_atomic_int_compare_and_exchange_full) (gint *atomic,
gint oldval,
gint newval,
gint *preval)
{
return g_atomic_int_compare_and_exchange_full (atomic, oldval, newval, preval);
}
Run Code Online (Sandbox Code Playgroud)
有人可以解释一下这段代码到底是做什么的吗?我对这里的几件事感到困惑:
函数名称g_atomic_int_compare_and_exchange_full
位于括号内。这有什么意义呢?
该函数的主体显然只包含对函数本身的调用,因此这将永远运行并导致堆栈溢出(双关语)。
我根本无法理解这个函数声明。这里究竟发生了什么?
我有一个头文件,其中包含
#define PROTOTYPE(s) s
Run Code Online (Sandbox Code Playgroud)
这有什么意义呢?似乎它将只是用自身替换输入。
还有它周围的其他指令吨,但似乎有如果它被定义任何影响只是检查只有一个:#ifndef PROTOTYPE
。我在HDF4头文件中找到了执行以下操作的位置:#define PROTOTYPE
。因此,这些都不能真正解决我的问题。似乎还是没用的。
使用方法如下:
CS_RETCODE clientmsg_callback PROTOTYPE((
CS_CONTEXT * context,
CS_CONNECTION *connection,
CS_CLIENTMSG *clientmsg));
Run Code Online (Sandbox Code Playgroud)
这是使用Sybase Open Client的项目的一部分。稍后在此处使用clientmsg_callback:
ct_callback(context, NULL, CS_SET, CS_CLIENTMSG_CB,
(CS_VOID *)clientmsg_callback);
Run Code Online (Sandbox Code Playgroud)
我将从这里开始一个示例程序:
clientmsg_callback稍后实现。我认为该示例最初是考虑到C而不是C ++编写的。也许与它有关?
我想在x
一个打开的缓冲区的每一行上运行一个我刚刚记录在寄存器中的宏,从我的光标到缓冲区的末尾,在vim中.我怎么做?
我知道我可以重播宏n次:
15@x
Run Code Online (Sandbox Code Playgroud)
...或者只是按住@
直到我到达最后一行,但我想点击几下击键并完成它.
提前致谢.
我想在选择中的每一行上运行一个宏,而不是总计我头脑中的行数.例如,我可能会编写一个宏来进行转换:
Last, First
Run Code Online (Sandbox Code Playgroud)
成
First Last
Run Code Online (Sandbox Code Playgroud)
我希望它能在所有这些方面运行:
Stewart, John
Pumpkin, Freddy
Mai, Stefan
...
Run Code Online (Sandbox Code Playgroud)
任何想法Vim大师?
编辑:这只是一个例子,显然这是一个琐碎的可复制,但还有其他一些实例,并不是那么容易,我宁愿使用宏.
当我在一个充满宏技巧和魔法的大项目中工作时,我偶然发现了一个错误,其中宏没有正确扩展。结果输出是“ EXPAND(0)
”,但EXPAND
被定义为“ #define EXPAND(X) X
”,所以显然输出应该是“ 0
”。
“没问题”,我心里想。“这可能是一些愚蠢的错误,这里有一些令人讨厌的宏,毕竟有很多地方会出错”。正如我所想的那样,我将行为不当的宏隔离到他们自己的项目中,大约 200 行,并开始使用 MWE 来查明问题。200 行变成了 150,然后又变成了 100,然后是 20、10……令我震惊的是,这是我最后的 MWE:
#define EXPAND(X) X
#define PARENTHESIS() ()
#define TEST() EXPAND(0)
EXPAND(TEST PARENTHESIS()) // EXPAND(0)
Run Code Online (Sandbox Code Playgroud)
4 行。
雪上加霜的是,几乎对宏的任何修改都会使它们正常工作:
#define EXPAND(X) X
#define PARENTHESIS() ()
#define TEST() EXPAND(0)
// Manually replaced PARENTHESIS()
EXPAND(TEST ()) // 0
Run Code Online (Sandbox Code Playgroud)
#define EXPAND(X) X
#define PARENTHESIS() ()
#define TEST() EXPAND(0)
// Manually replaced TEST()
EXPAND(EXPAND(0)) // 0
Run Code Online (Sandbox Code Playgroud)
// Set EXPAND to 0 instead of X
#define …
Run Code Online (Sandbox Code Playgroud) 我已经写了一点C,我可以很好地阅读它以大致了解它在做什么,但每次我遇到一个宏它都完全抛弃了我.我最终必须记住宏是什么,并在我阅读时将其替换为我的脑袋.我遇到的那些直观且易于理解的东西总是像迷你小功能一样,所以我总是想知道为什么它们不仅仅是功能.
我可以理解在预处理器中为调试或跨平台构建定义不同构建类型的需要,但是定义任意替换的能力似乎只对使得已经很难理解的语言更加难以理解.
为什么为C引入了如此复杂的预处理器?并且有没有人有一个使用它的例子,这将使我理解为什么它似乎仍然用于除了简单的#debug风格条件编译之外的目的?
编辑:
读了很多答案之后我还是不明白.最常见的答案是内联代码.如果内联关键字没有这样做,那么它有充分的理由不这样做,或者实现需要修复.我不明白为什么需要一个完全不同的机制,这意味着"真正内联这个代码"(除了形成内联之前编写的代码).我也不明白提到"如果它太愚蠢而不能被赋予功能"的想法.当然,任何需要输入并产生输出的代码都最好放在一个函数中.我想我可能没有得到它,因为我不习惯编写C的微观优化,但预处理器只是对一些简单问题的复杂解决方案.
我将从一个例子开始.这里的List.fill
元组与Scala 2.10中的宏相当:
import scala.language.experimental.macros
import scala.reflect.macros.Context
object TupleExample {
def fill[A](arity: Int)(a: A): Product = macro fill_impl[A]
def fill_impl[A](c: Context)(arity: c.Expr[Int])(a: c.Expr[A]) = {
import c.universe._
arity.tree match {
case Literal(Constant(n: Int)) if n < 23 => c.Expr(
Apply(
Select(Ident("Tuple" + n.toString), "apply"),
List.fill(n)(a.tree)
)
)
case _ => c.abort(
c.enclosingPosition,
"Desired arity must be a compile-time constant less than 23!"
)
}
}
}
Run Code Online (Sandbox Code Playgroud)
我们可以使用以下方法:
scala> TupleExample.fill(3)("hello")
res0: (String, String, String) = (hello,hello,hello)
Run Code Online (Sandbox Code Playgroud)
这个家伙在几个方面都是一只奇怪的鸟.首先,arity
参数必须是一个文字整数,因为我们需要在编译时使用它.在Scala的早期版本中,(根据我所知),方法甚至无法判断其中一个参数是否是编译时文字.
其次, …
所以我最近讨论了我的工作,其中我质疑使用双重防守对一名后卫的影响.双防护的意思如下:
头文件"header_a.hpp":
#ifndef __HEADER_A_HPP__
#define __HEADER_A_HPP__
...
...
#endif
Run Code Online (Sandbox Code Playgroud)
将头文件包含在头文件或源文件中的任何位置时:
#ifndef __HEADER_A_HPP__
#include "header_a.hpp"
#endif
Run Code Online (Sandbox Code Playgroud)
现在我明白在头文件中使用guard是为了防止多次包含已经定义的头文件,这是常见的并且有很好的文档记录.如果已经定义了宏,则编译器会将整个头文件视为"空白",并防止双重包含.很简单.
我不明白的问题是使用#ifndef __HEADER_A_HPP__
和#endif
围绕着#include "header_a.hpp"
.同事告诉我,这为夹杂物增加了第二层保护,但是如果第一层绝对完成工作(或者它是什么?),我看不出第二层是如何有用的.
我能想到的唯一好处是它可以直接阻止链接器找到文件.这是否意味着改善编译时间(没有提到作为一个好处),或者在这里有什么其他工作我没有看到?
在Objective-C
它是使用静态字符串常量来定义备用API键(例如发布和调试键之间进行区分用于分析套件,像MixPanel,乱舞或Crashlytics)有时是有用的:
#if DEBUG
static NSString *const API_KEY = @"KEY_A";
#else
static NSString *const API_KEY = @"KEY_B";
#endif
Run Code Online (Sandbox Code Playgroud)
然后...
[Analytics startSession:API_KEY];
Run Code Online (Sandbox Code Playgroud)
这是如何转换为Swift的,因为Swift编译器不再使用预处理器?
macros ×10
c ×3
c++ ×3
vim ×2
function ×1
glib ×1
line ×1
linker ×1
preprocessor ×1
scala ×1
scala-2.10 ×1
scala-macros ×1
swift ×1
xcode ×1