第23课 - #error 和 #line 使用分析

第23课 - #error 和 #line 使用分析

1. #error 的用法

(1)#error 是一个预处理器指示字,用于生成一个编译错误消息,这个消息最终会传递到编译器(gcc)

         在思考这一点的过程中,领悟到了两个点:

         ① 使用 gcc 编译代码,输出的错误(警告)信息,是由预处理器、编译器、汇编器、链接器产生的。

         ② gcc表示整个编译过程,它会调用 预处理器程序 -> 编译器程序 -> 汇编器程序 -> 链接器程序

(2)使用方法:#error message     // 不需要在message上使用双引号

(3)#error 编译指示字用于自定义程序员特有的编译错误消息。类似的,#warning 用于生成编译警告错误

(4)#error 可用于提示编译条件是否满足。编译过程中的任何错误意味着无法生成最终的可执行程序。

 

下面我们通过一个示例程序来说明 #error 的用法:

下面是一段C++ 的代码,如果我们错误的使用gcc对其进行编译就会报错

 1 #include <stdio.h>
 2 
 3 class CppClass
 4 {
 5 private:
 6     int m_nValue;
 7 public:
 8     CppClass(){};
 9     ~CppClass(){};
10 };
11 
12 int main()
13 {
14     return 0;
15 }

使用gcc编译该代码报错  

 

 那如何解决这个问题呢?答案就是使用 条件编译 + #error 

 1 #include <stdio.h>
 2 
 3 // __cplusplus宏是C++编译器内置的一个宏,C编译器中是没有的
 4 // 如果使用C编译器编译该程序#error就会报编译报错
 5 #ifndef __cplusplus
 6     #error This file should be processed with C++ compiler
 7 #endif
 8 
 9 class CppClass
10 {
11 private:
12     int m_nValue;
13 public:
14     CppClass(){};
15     ~CppClass(){};
16 };
17 
18 int main()
19 {
20     return 0;
21 }

 

在上篇文章的最后,我们分析了一个通过条件编译区分产品版本的小程序,在那个代码中我们没有考虑一种情况,那就是如果没有定义PRODUCT这个宏会怎么样?

#include <stdio.h>

void f()
{
#if (PRODUCT == 1)
    printf("This is a low level product!\n");
#elif (PROUDCT == 2)
    printf("This is a middle level product!\n");
#elif (PRODUCT == 3)
    printf("This is a high level product!\n");
#endif
}

int main()
{
    f();
    
    printf("1. Query Information.\n");
    printf("2. Record Information.\n");
    printf("3. Delete Information.\n");
    
#if (PRODUCT == 1)
    printf("4. Exit.\n");
#elif (PRODUCT == 2)
    printf("4. High Level Query.\n");
    printf("5. Exit.\n");
#elif (PRODUCT == 3)
    printf("4. High Level Query.\n");
    printf("5. Mannual Service.\n");
    printf("6. Exit.\n");
#endif
    
    return 0;
}

如果我们在编译该程序时没有通过-DPRODUCT指定这个宏的值,编译并不会报错但是执行结果就有问题了

使用 #error 完善该程序,如果没有定义PRODUCT或者PRODUCT的值不为1、2、3中的一个,程序在编译时就会报错。

 1 #include <stdio.h>
 2 
 3 void f()
 4 {
 5 #if (PRODUCT == 1)
 6     printf("This is a low level product!\n");
 7 #elif (PROUDCT == 2)
 8     printf("This is a middle level product!\n");
 9 #elif (PRODUCT == 3)
10     printf("This is a high level product!\n");
11 #else
12     // 如果PRODUCT未定义或定义了但!=1 != 2 != 3
13     #error The PRODUCT macro is NOT defined!
14 #endif
15 }
16 
17 int main()
18 {
19     f();
20     
21     printf("1. Query Information.\n");
22     printf("2. Record Information.\n");
23     printf("3. Delete Information.\n");
24     
25 #if (PRODUCT == 1)
26     printf("4. Exit.\n");
27 #elif (PRODUCT == 2)
28     printf("4. High Level Query.\n");
29     printf("5. Exit.\n");
30 #elif (PRODUCT == 3)
31     printf("4. High Level Query.\n");
32     printf("5. Mannual Service.\n");
33     printf("6. Exit.\n");
34 #else
35     // 如果PRODUCT未定义或定义了但!=1 != 2 != 3
36     #error The PRODUCT macro is NOT defined!
37 #endif
38     
39     return 0;
40 }

2. #line 的用法

(1)#line 用于强制指定新的行号和编译文件名,并对源程序的代码重新编号

(2)用法: 

            ① #line number newFilename

            ② #line number     // 不改变文件名,只改变行号

(3)#line 编译指示字的本质是重定义 __LINE__ __FILE__

 1 #include <stdio.h>
 2 
 3 int main()
 4 {
 5     printf("%s : %d\n", __FILE__, __LINE__);
 6 
 7     #line 1 "new_line.c"    // 这里改变了行号和文件名,行号为1(下一行行号为1)、文件名为new_line.c(注意这里需要使用用双引号)
 8 
 9     printf("%s : %d\n", __FILE__, __LINE__);
10 
11     return 0;
12 }

// 输出结果

    swj@ubuntu:~/c_course/ch_23$ ./a.out
    line.c : 5
    new_line.c : 2

#line 是C语言早期的产物(在当今的软件工程中已经不使用了),那时候代码量比较小,通常放到一个文件中。如果这个程序由几个人分工协作完成的话,就是每个人先各写各的,最后再统一放到一个文件中。

那如果编译发生错误,如何知道错误的代码是谁写的呢?这个就要使用 #line 预处理指令了。 

 1 #include <stdio.h>
 2 
 3 // The code section is written by A.
 4 // Begin
 5 #line 1 "a.c"
 6 
 7 // End
 8 
 9 // The code section is written by B.
10 // Begin
11 #line 1 "b.c"
12 
13 // End
14 
15 // The code section is written by Scott.
16 // Begin
17 #line 1 "scott_shi.c"
18 
19 
20 int main()
21 {
22     printf("%s : %d\n", __FILE__, __LINE__);
23     
24     printf("%s : %d\n", __FILE__, __LINE__)    // 这里编译会报错
25     
26     return 0;
27 }
28 
29 // End

 编译报错,提示是 scott_shi.c 这个文件的 第9行 发生错误,这样就定位了是哪个人写的。

 

posted @ 2019-11-13 22:56  Hengs  阅读(627)  评论(0编辑  收藏  举报