我正在尝试定义一个宏 -
#define macro1(arg1) \
do{ \
int _state = 0; \
if (arg1 && arg1->member_) \
_state = arg1->member_->state_; \
printf("%d", _state); \
} while(0)
A *a = new A():
macro1(a); // Works
macro1(NULL); // Error
我看到的具体错误是 -
"错误:' - >'的基本操作数不是指针"
Aren我们允许将NULL
作为参数传递给宏吗?
答案 0 :(得分:2)
宏扩展只是文本替换,因此当您通过NULL
时,它会扩展为NULL->member
,显然这是一个错误。一种方法是使用临时变量:
#define macro1(arg1) \
do{ \
A* p = (arg1);
int _state = 0; \
if (p && p->member_) \
_state = p->member_->state_; \
printf("%d", _state); \
} while(0)
A *a = new A():
macro1(a);
macro1(NULL);
这样两种情况都可以。
答案 1 :(得分:2)
你必须了解什么是宏才能理解你的错误。除了编译器之外,还有一种叫做预编译器的动物。它通过为此宏定义的实际代码替换所有宏的引用。所以这段代码:
#define macro1(arg1) \
do{ \
int _state = 0; \
if (arg1 && arg1->member_) \
_state = arg1->member_->state_; \
printf("%d", _state); \
} while(0)
A *a = new A():
macro1(a); // Works
macro1(NULL); // Error
将替换为:
A *a = new A():
do{
int _state = 0;
if (a && a->member_)
_state = a->member_->state_;
printf("%d", _state);
} while(0)
do{
int _state = 0;
if (NULL && NULL->member_)
_state = NULL->member_->state_;
printf("%d", _state);
} while(0)
将编译此代码。现在,您可以自己查看编译错误的根本原因。
答案 2 :(得分:1)
宏只是一个文本替代品。
例如,如果你有
#define mac(x) x/x
适用于必须数字但不适用于0
,因为它将替换为未定义的0/0
。
如果您通过NULL
,则会将其替换为:
do{ \
int _state = 0; \
if (NULL && NULL->member_) \
_state = NULL ->member_->state_; \
printf("%d", _state); \
} while(0)
那么NULL->member_
在这种情况下的意义是什么。没有意义,因此失败了。
考虑使用常规函数,或者两个宏用于常规指针,一个用于NULL
指针,并将代码设置为:
if (ptr)
macro1(ptr);
else
macro2;
答案 3 :(得分:1)
小调整让预编译器知道类型大小+前向声明,它将起作用:
#define macro1(arg1) \
do{ \
int _state = 0; \
if ((arg1) && ((A*)arg1)->member_) \
_state = ((A*)arg1)->member_->state_; \
printf("%d", _state); \
} while(0)
完整代码:
#include <stdio.h>
class A;
#define macro1(arg1) \
do{ \
int _state = 0; \
if ((arg1) && ((A*)arg1)->member_) \
_state = ((A*)arg1)->member_->state_; \
printf("%d", _state); \
} while(0)
struct member{
int state_;
};
class A {
public:
member* member_;
};
int main(int n, char** arg) {
A* a = new A();
a->member_ = new member();
a->member_->state_ = 1;
macro1(a);
macro1(NULL);
return 0;
}
答案 4 :(得分:1)
更基本的问题是#.handlers = 1catalina.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
.handlers = 1catalina.org.apache.juli.FileHandler
#1catalina.org.apache.juli.FileHandler.level = FINE
#1catalina.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
#1catalina.org.apache.juli.FileHandler.prefix = catalina.
1catalina.java.util.logging.FileHandler.level = FINE
1catalina.java.util.logging.FileHandler.pattern = ${catalina.base}/logs/catalina.%g.log
1catalina.java.util.logging.FileHandler.limit = 13107200
1catalina.java.util.logging.FileHandler.count = 5
1catalina.java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
不是指针,它是0的宏。
因此,当你传入NULL
时,它相当于传入0,这当然是一个错误。
正如其他答案所提到的,给论证一个明确的演员会解决它
NULL
作为旁注,您应该在C ++中使用(A*)arg1
作为空指针。
编辑:正如@AjayBrahmakshatriya所指出的那样,nullptr
可以定义为NULL
(仅限C),这将是一个指针,但参数仍然成立, (void*)0
不是您的类型的指针。
EDIT2 :显然在C ++ 11及更高版本中,NULL
可以定义为NULL