我正在读一本书来学习 C 。在那本书中,下面的示例代码给出了gcc(Debian 4.7.2-4)4.7.2的预处理程序错误。错误是:
file.c:在函数'main'中:
file.c:16:14:error:token“”我知道C语言。\ n“”在预处理程序表达式中无效
file.c:20:14:error:token“”我知道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预处理器是否无法正确执行此操作,或者是否需要更改代码有问题?
答案 0 :(得分:2)
正如@cebarth指出的那样,问题是在第一个C_LANG
中重新定义B_LANG
和#if
后,#elif
子句失败,因为扩展是:
#elif "I know the C language.\n" == 'C'
/*...*/
#elif "I know BASIC.\n" == 'B'
C标准说明#if
和#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
答案 1 :(得分: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;
}
答案 2 :(得分: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
无需使用宏定义。您可以通过简单地将一个字符添加到EUTE C_LANG或B_LANG:
来更改打印的内容#define C_LANGn
#define B_LANGn
这样代码更具可读性。