1

我正在读一本书来学习C。在那本书中,下面的示例代码给出了 gcc (Debian 4.7.2-4) 4.7.2 的预处理器错误。错误是:

file.c:在函数'main'中:
file.c:16:14:错误:令牌“我知道 C 语言。\n””在预处理器表达式中无效
file.c:20:14:错误:令牌""我知道 BASIC。\n"" 在预处理器表达式中无效

代码是:

#include <stdio.h>

#define C_LANG    'C'
#define B_LANG    'B'
#define NO_ERROR  0

int main(void)
{
   #if C_LANG == 'C' && B_LANG == 'B'
     #undef C_LANG
     #define C_LANG "I know the C language.\n"
     #undef B_LANG
     #define B_LANG "I know BASIC.\n"
     printf("%s%s", C_LANG, B_LANG);
   #elif C_LANG == 'C'
     #undef C_LANG
     #define C_LANG "I only know C language.\n"
     printf("%s", C_LANG);
   #elif B_LANG == 'B'
     #undef B_LANG
     #define B_LANG "I only know BASIC.\n"
     printf("%s", B_LANG);
   #else
     printf("I don't know C or BASIC.\n");
   #endif

   return NO_ERROR;
}

gcc 预处理器是否无法正确执行此操作,或者代码有问题需要更改?

4

3 回答 3

2

正如@cebarth 指出的那样,问题是在您重新定义C_LANGB_LANG在 first#if之后,#elif子句失败,因为扩展是:

   #elif "I know the C language.\n" == 'C'
   /*...*/
   #elif "I know BASIC.\n" == 'B'

#ifC 标准对and #elif(C99 6.10.1)这么说:

表单的预处理指令
# if constant-expression new-line groupopt
# elif constant-expression new-line groupopt
检查控制常量表达式的计算结果是否为非零。

由于先前的检查已成功,因此没有提及不评估表达式。

解决此问题的一种方法是在printf().

     #undef C_LANG
     #define C_LANG "I know the C language.\n"
     #undef B_LANG
     #define B_LANG "I know BASIC.\n"
     printf("%s%s", C_LANG, B_LANG);
     #undef C_LANG
     #define C_LANG 'C'
     #undef B_LANG
     #define B_LANG 'B'

解决此问题的另一种方法是显式使用#else而不是#elif.

   #if C_LANG == 'C' && B_LANG == 'B'
     #undef C_LANG
     #define C_LANG "I know the C language.\n"
     #undef B_LANG
     #define B_LANG "I know BASIC.\n"
     fprintf(stdout, "%s%s", C_LANG, B_LANG);
   #else
     #if C_LANG == 'C'
       #undef C_LANG
       #define C_LANG "I only know C language.\n"
       printf("%s", C_LANG);
     #elif B_LANG == 'B'
       #undef B_LANG
       #define B_LANG "I only know BASIC.\n"
       printf("%s", B_LANG);
     #else
       printf("I don't know C or BASIC.\n");
     #endif
   #endif
于 2013-05-20T18:45:18.537 回答
0
#include <stdio.h>

#define C_LANG    'C'
#define B_LANG    'B'
#define NO_ERROR  0

int main(void)
{
   #if C_LANG == 'C' && B_LANG == 'B'
     #define C_LANG_VALUE "I know the C language.\n"
     #define B_LANG_VALUE "I know BASIC.\n"
     printf("%s%s", C_LANG_VALUE, B_LANG_VALUE);
   #elif C_LANG == 'C'
     #define C_LANG_VALUE "I only know C language.\n"
     printf("%s", C_LANG_VALUE);
   #elif B_LANG == 'B'
     #define B_LANG_VALUE "I only know BASIC.\n"
     printf("%s", B_LANG_VALUE);
   #else
     printf("I don't know C or BASIC.\n");
   #endif

   return NO_ERROR;
}
于 2013-05-20T18:47:45.363 回答
0

通常混合预处理器代码和非预处理器代码不是一个好主意,因为很难遵循执行路径(嗯,大多数时候)。

对于您的特定示例,您可以采取一些措施使事情变得更容易:

#define C_LANG 
#define B_LANG  
#define NO_ERROR

#if defined(C_LANG) || defined (B_LANG)
   #if defined(C_LANG)
       printf ("I know the C language.\n");
   #else
       printf ("I know the BASIC language.\n");
   #endif
#else
   printf("I don't know C or BASIC.\n");
#endif

无需使用宏定义。您可以通过在eiter C_LANG 或B_LANG 中添加一个字符来更改打印的内容:

#define C_LANGn
#define B_LANGn 

这样代码的可读性就更高了。

于 2016-04-27T10:56:42.990 回答