可能重复:
什么是C宏有用?
每隔几个月我就会学到一些C,这是我的废话大学编程教育从未涉及过的.今天它是宏.我对宏的基本理解是它们是一个简单的搜索和替换,它会在编译之前发生在代码上.我无法理解你为什么要使用宏.我正在看的大多数基本例子都是这样的
TEST(a,%d);
#define TEST(a,b) printf(" The value of " #a " = " #b " \n", a)
//which expands to
printf(" The value of a = %d \n",a);
Run Code Online (Sandbox Code Playgroud)
(例子来自这里)
从我的新手角度来看,似乎定义一个新函数会给你相同的结果.我可以看到历史上宏如何在易于搜索和替换之前的几天内快速修改大量源代码,但有些东西告诉我,我错过了一些更重要的观点.
那么宏可以为你做什么样的有用的事情呢?
在我的程序中,我多次在控制台中读取整数.每次,我都要输入这一行.
new Scanner(System.in).nextInt();
Run Code Online (Sandbox Code Playgroud)
我已经习惯了C/C++而且我想知道我是否可以定义类似的东西
#define READINT Scanner(System.in).nextInt();
Run Code Online (Sandbox Code Playgroud)
然后,在我的java程序的每个地方,我都可以读取表单控制台
int a = new READINT;
Run Code Online (Sandbox Code Playgroud)
但我读的表格书Java不支持宏.
有人请解释我为什么会这样,我可以用其他任何方式做到这一点.
我习惯于从Haskell那里进行懒惰的评估,并且发现自己因为我已经正确地使用了懒惰的评估而感到厌烦.这实际上是非常具有破坏性的,因为我使用的其他语言主要是懒得评估一些非常笨拙的东西,通常涉及自定义迭代器的推出等等.所以只是通过获取一定的了解,其实我已经自己做了少在我原来的语言生产力.叹.
但我听说AST宏提供了另一种干净的方式来做同样的事情.我经常听到诸如"懒惰评估使宏多余"的陈述,反之亦然,主要来自于对Lisp和Haskell社区的争吵.
我已经涉足各种Lisp变种中的宏.它们看起来像是一种非常有组织的复制和粘贴代码块的方式,可以在编译时处理.他们当然不是Lispers认为的圣杯.但这几乎可以肯定是因为我无法正确使用它们.当然,让宏系统在与语言本身组合在一起的相同核心数据结构上工作是非常有用的,但它仍然基本上是一种复制和粘贴代码的有组织方式.我承认,基于与允许完全运行时更改的语言相同的AST的宏系统是强大的.
我想知道的是,如何使用宏来简明扼要地进行懒惰评估呢?如果我想逐行处理文件而不会搞砸整个事情,我只返回一个列表,其中有一个映射到它的行读取例程.这是DWIM的完美例子(尽我所能).我甚至不必考虑它.
我显然没有得到宏.我已经使用过它们并且在炒作时并没有特别留下深刻的印象.因此,我缺少一些我没有通过在线阅读文档获得的东西.有人可以向我解释这一切吗?
我已经阅读了很多内容,LISP可以动态地重新定义语法,大概是宏.我好奇这到底有多远?你能重新定义语言结构,以至于它的边界成为另一种语言的编译器吗?例如,您是否可以将LISP的功能性质更改为更面向对象的语法和语义,或许可以说语法更接近像Ruby这样的东西?
特别是,是否可以使用宏来摆脱括号地狱?我已经学会了足够的(Emacs-)LISP来使用我自己的微功能定制Emacs,但我很好奇宏可以在定制语言方面走多远.
由于本答案中描述的原因,我经常在我的#defines中使用do-while(0)构造.此外,我正在尝试使用尽可能高的编译器警告级别来捕获更多潜在问题,并使我的代码更加健壮和跨平台.所以我通常使用-Wall
gcc和/Wall
MSVC.
不幸的是,MSVC抱怨do-while(0)构造:
foo.c(36) : warning C4127: conditional expression is constant
Run Code Online (Sandbox Code Playgroud)
我应该怎么做这个警告?
只是为所有文件全局禁用它?对我来说这似乎不是一个好主意.
为什么GCC头文件中的常量表达式被括号括起来,像这样?
#define INTMAX_MIN (-9223372036854775807LL)
#define INTMAX_MAX (9223372036854775807LL)
Run Code Online (Sandbox Code Playgroud)
如果我省略括号,这会有什么不同?
#define INTMAX_MIN -9223372036854775807LL
#define INTMAX_MAX 9223372036854775807LL
Run Code Online (Sandbox Code Playgroud)
为什么有'L'后缀?如果我写以下内容会是一样的吗?
#define INTMAX_MIN -9223372036854775807
#define INTMAX_MAX 9223372036854775807
Run Code Online (Sandbox Code Playgroud)
是否有实际用途或者总是相同的东西?
我知道'L'代表很长时间,我也很清楚C宏中括号的重要性; 我是为了好奇而问这个.
我如何在编译时使用gcc取消定义编译器宏.我尝试了一些编译args到gcc像-D但我无法看到"未定义"的消息.
谢谢
#include <iostream>
#define MYDEF
int main(){
#ifdef MYDEF
std::cout<<"defined\n";
#else
std::cout<<"not defined\n";
#endif
}
Run Code Online (Sandbox Code Playgroud) 所以我有这个宏:
import language.experimental.macros
import scala.reflect.macros.Context
class Foo
class Bar extends Foo { def launchMissiles = "launching" }
object FooExample {
def foo: Foo = macro foo_impl
def foo_impl(c: Context): c.Expr[Foo] =
c.Expr[Foo](c.universe.reify(new Bar).tree)
}
Run Code Online (Sandbox Code Playgroud)
我已经说了三次我想要foo
返回一个Foo
,但我可以做以下(在2.10.0-RC3中):
scala> FooExample.foo
res0: Bar = Bar@4118f8dd
scala> res0.launchMissiles
res1: String = launching
Run Code Online (Sandbox Code Playgroud)
如果我删除任何一个上的类型参数,也会发生同样的事情c.Expr
.如果我真的想确保无论谁打电话foo
都看不到他们正在获得Bar
,我必须在树本身添加类型归属.
这实际上非常棒 - 例如,我可以将宏指向某种类型的模式,并Vocabulary
使用表示词汇表中的术语的成员方法创建某个类的匿名子类,这些将在返回的对象上可用.
我想知道我到底在做什么,所以我有几个问题.首先,该foo
方法实际上的返回类型是什么?它是否仅适用于(可选)文档?它明确地约束了返回类型(例如,Int
在这种情况下我无法将其更改为),如果我将其完全删除,则会出现如下错误:
scala> FooExample.foo
<console>:8: error: type mismatch;
found : Bar
required: Nothing
FooExample.foo …
Run Code Online (Sandbox Code Playgroud) 我在我的代码中使用了JUCE库和一些Boost头文件.Juce将"T"定义为宏(呻吟),Boost经常在其模板定义中使用"T".结果是,如果你以某种方式在Boost头之前包含JUCE头,那么预处理器会扩展Boost代码中的JUCE宏,然后编译器就会无可救药地丢失.
在大多数情况下保持我的包含顺序并不难,但是当你有一个包含一些其他类的JUCE类时,它会变得棘手,在链上的某个地方,一个文件包含Boost,如果有任何文件在它之前需要JUCE包括你遇到麻烦.
我最初的希望是解决这个问题
#undef T
Run Code Online (Sandbox Code Playgroud)
之前任何包括Boost.但问题是,如果我不重新定义它,那么其他代码会混淆"T"未被声明.
然后我想也许我可以这样做一些循环的#define技巧:
// some includes up here
#define ___T___ T
#undef T
// include boost headers here
#define T ___T___
#undef ___T___
Run Code Online (Sandbox Code Playgroud)
丑陋,但我认为它可能有用.
可悲的是没有.我在使用"T"作为宏的地方出错
'___T___' was not declared in this scope.
Run Code Online (Sandbox Code Playgroud)
有没有办法让这两个库可靠地一起工作?
在阅读各种C和C++源代码时,我遇到了两个宏__APPLE__
和__OSX__
.我发现__OSX__
在各种代码中有很多用处,特别是那些来自*BSD
系统的代码.
但是,有时候我发现__OSX__
仅仅测试是不够的,我必须用__APPLE__
宏来完成测试.
该移植Unix命令行工具到Mac OS X引导指定__APPLE__
,此外__APPLE_CC__
但没有提及__OSX__
.
- 使用
#ifdef __GNUC__
封装任意GCC特定的代码.- 使用
#ifdef __APPLE_CC__
封装任意Mac OS X的特定代码.
再一次,没有提到__OSX__
宏观.
在Mac OS X平台和XCode开发环境中预定义了哪些宏应该用于区分C/C++程序中的OSX特定代码?
__OSX__
宏定义在哪里?是*BSD
具体的宏吗?