忽略分号C语法

时间:2014-03-31 02:42:24

标签: c syntax macros

  • 平台:Linux 3.2.0 x86(Debian Wheezy)
  • 编译:GCC 4.7.2(Debian 4.7.2-5)

我正在编写一个返回指向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的定义,它更具可读性。我已经尝试使用不必要的分号,我的编译器没有抱怨,我可以告诉功能正常工作。所以我的问题是,是不必要的分号法律语法。如果合法是正确的吗?

4 个答案:

答案 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