我正在编写一个返回指向char的指针的函数。我仍然希望"返回"一个整数值,表示发生的错误,因此该函数将一个指向一个将用作标志的整数的指针作为参数。以下是声明的示例
char* foo(int *flag, etc.)
如果用户不想知道发生了什么特定错误,我想允许flag
为NULL,因为它可能无关紧要(我不知道它是否存在,这个想法只是理论上的)。如果发生错误,我会写下以下内容,
... //Symbolic Code
if(error) //Some error has occured
{
if(flag != NULL) *flag = SOME_ERR_VALUE; //Set the flag variable
return NULL; //return NULL to show that an error occured
}
不是一遍又一遍地编写代码,而是想为它编写一个宏。但是代码不止一个语句,这意味着我必须将宏放在它自己的代码块中,或者宏必须已经在它自己的代码块中。例如。
#define RETFLAG(err, ret) if(flag != NULL) *flag = err; return ret;
... //Symbolic Code
if(error) //Some error has occured
{RETFLAG(1, NULL)} //Notice the {}
另一种方法是,
//Notice the {} in the definition
#define RETFLAG(err, ret) {if(flag != NULL) *flag = err; return ret;}
... //Symbolic Code
if(error) //Some error has occured
RETFLAG(1, NULL)
这两种方法都可行,但我不喜欢借调的方法,因为我想在宏的末尾添加分号,这样,
//Notice the {} in the definition
#define RETFLAG(err, ret) {if(flag != NULL) *flag = err; return ret;}
... //Symbolic Code
if(error) //Some error has occured
RETFLAG(1, NULL); //The only difference is the semicolon
我知道分号是不必要的,但我认为如果你没有真正查看RETFLAG的定义,它更具可读性。我已经尝试使用不必要的分号,我的编译器没有抱怨,我可以告诉功能正常工作。所以我的问题是,是不必要的分号法律语法。如果合法是正确的吗?
答案 0 :(得分:6)
根本不需要宏。
inline char *fail_with_reason(int *flag, int reason)
{
if (flag) *flag = reason;
return NULL;
}
然后你的职能会说
if (error) return fail_with_reason(flag, 1);
答案 1 :(得分:5)
您可以使用do { ... } while(0)
。
#define RETFLAG(err, ret) do { if(flag != NULL) *flag = (err); return NULL; } while(0)
if (error)
RETFLAG(1, NULL);
这样,您不必担心范围,也没有额外的分号。
答案 2 :(得分:2)
没有表达式的;
只是一个空语句,完全合法,来自C99草案标准部分6.8.3
表达式和空语句:
null语句(仅由分号组成)不执行任何操作。
但是除了你的简单例子之外,这还有一些缺陷,正如Raymond在他的评论中指出的那样do while trick需要将代码包装在do {} while(0)
块中,有助于克服,正如公认的答案所说:< / p>
do ... while和if ... else是为了让你的宏后面的分号总是意味着相同的东西[...]
答案 3 :(得分:1)
逗号可能有帮助
#define RETFLAG(err, ret) if(flag != NULL) return *flag = err, NULL
修正:
#define RETFLAG(err, ret) return NULL == flag ? NULL : *flag = err, NULL