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

1. #error 的用法

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

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

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

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

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

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

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

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

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

 #include <stdio.h>

 class CppClass
{
private:
int m_nValue;
public:
CppClass(){};
~CppClass(){};
}; int main()
{
return ;
}

使用gcc编译该代码报错

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

 #include <stdio.h>

 // __cplusplus宏是C++编译器内置的一个宏,C编译器中是没有的
// 如果使用C编译器编译该程序#error就会报编译报错
#ifndef __cplusplus
#error This file should be processed with C++ compiler
#endif class CppClass
{
private:
int m_nValue;
public:
CppClass(){};
~CppClass(){};
}; int main()
{
return ;
}

在上篇文章的最后,我们分析了一个通过条件编译区分产品版本的小程序,在那个代码中我们没有考虑一种情况,那就是如果没有定义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 ;
}

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

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

 #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");
#else
// 如果PRODUCT未定义或定义了但!=1 != 2 != 3
#error The PRODUCT macro is NOT defined!
#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");
#else
// 如果PRODUCT未定义或定义了但!=1 != 2 != 3
#error The PRODUCT macro is NOT defined!
#endif return ;
}

2. #line 的用法

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

(2)用法:

① #line number newFilename

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

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

 #include <stdio.h>

 int main()
{
printf("%s : %d\n", __FILE__, __LINE__); #line 1 "new_line.c" // 这里改变了行号和文件名,行号为1(下一行行号为1)、文件名为new_line.c(注意这里需要使用用双引号) printf("%s : %d\n", __FILE__, __LINE__); return ;
} // 输出结果

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

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

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

 #include <stdio.h>

 // The code section is written by A.
// Begin
#line 1 "a.c" // End // The code section is written by B.
// Begin
#line 1 "b.c" // End // The code section is written by Scott.
// Begin
#line 1 "scott_shi.c" int main()
{
printf("%s : %d\n", __FILE__, __LINE__); printf("%s : %d\n", __FILE__, __LINE__) // 这里编译会报错 return ;
} // End

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

第23课 - #error 和 #line 使用分析的更多相关文章

  1. 第23课 #error和#line使用分析

    #error的用法: 示例程序: #include <stdio.h> #ifndef __cplusplus #error This file should be processed w ...

  2. #error和#line使用分析

    #error的用法 #error用于生成一个编译错误消息 用法:error message(不需要用双引号包围) #error编译指示字用于自定义程序员特有的编译错误,消息类似的 #warning用于 ...

  3. Error on line -1 of document : Premature end of file. Nested exception: Premature end of file.

    启动tomcat, 出现, ( 之前都是好好的... ) [lk ] ERROR [08-12 15:10:02] [main] org.springframework.web.context.Con ...

  4. 关于xml加载提示: Error on line 1 of document : 前言中不允许有内容

    我是在java中做的相关测试, 首先粘贴下报错: 读取xml配置文件:xmls\property.xml org.dom4j.DocumentException: Error on line 1 of ...

  5. (转载)Flash Loader加载完成不发送COMPLETE和ERROR事件的问题分析

    (转载)http://blog.dou.li/flash-loader%E5%8A%A0%E8%BD%BD%E5%AE%8C%E6%88%90%E4%B8%8D%E5%8F%91%E9%80%81co ...

  6. error on line 1 at column 6: XML declaration allowed only at the start of the document

    This page contains the following errors: error on line 1 at column 6: XML declaration allowed only a ...

  7. "fatal: protocol error: bad line length character: No This"

    git clone 远程地址时候出现 "fatal: protocol error: bad line length character: No This" 错误 在stackov ...

  8. Parse Fatal Error at line 41 column 24: 元素类型 "url-pattern" 必须由匹配的结束标记 "</url-pattern>" 终止

    1.错误描述 严重: Parse Fatal Error at line 41 column 24: 元素类型 "url-pattern" 必须由匹配的结束标记 "< ...

  9. (转)Windows 平台下解决httpd.exe: syntax error on line 39

    近来在研究PHP,结果为了Apache的安装伤神不已...小白我在安装后,启动Apache的服务虽然可以,不过,在Apache sevice monitor 中启动services时就会出现如下的问题 ...

随机推荐

  1. 粗略总结for循环与foreach()循环区别

    for循环和foreach循环其实可以算得上是从属关系的,即foreach循环是可以转化成for循环,但是for循环不一定能转换成foreach循环. 下面简单介绍一下两种循环: .for循环 代码格 ...

  2. ES6系列之项目中常用的新特性

    ES6系列之项目中常用的新特性 ES6常用特性 平时项目开发中灵活运用ES6+语法可以让开发者减少很多开发时间,提高工作效率.ES6版本提供了很多新的特性,接下来我列举项目中常用的ES6+的特性: l ...

  3. [Kong 与 Konga与postgres数据库] 之 Kuberneres 部署

    1.Kong的概述 Kong是一个clould-native.快速的.可扩展的.分布式的微服务抽象层(也称为API网关.API中间件或在某些情况下称为服务网格)框架.Kong作为开源项目在2015年推 ...

  4. Scala中的函数高级使用

    1.偏函数 1.基本介绍 在对符合某个条件,而不是所有情况进行逻辑操作时,使用偏函数是一个不错的选择 将包在大括号内的一组case语句封装为函数,我们称之为偏函数,它只对会作用于指定类型的参数或指定范 ...

  5. 如何使用python移除/删除非空文件夹?

    移除/删除非空文件夹/目录的最有效方法是什么? 1.标准库参考:shutil.rmtree. 根据设计,rmtree在包含只读文件的文件夹树上失败.如果要删除文件夹,不管它是否包含只读文件,请使用 i ...

  6. 兼容低版本IE浏览器的一些心得体会(持续更新)

    前言: 近期工作中,突然被要求改别人的代码,其中有一项就是兼容IE低版本浏览器,所以优雅降级吧. 我相信兼容低版本IE是许多前端开发的噩梦,尤其是改别人写的代码,更是痛不欲生. 本文将介绍一些本人兼容 ...

  7. WPF新手快速入门系列 1.布局

    [概要] 该系列文章主要描述,新手如何快速上手做wpf开发.看过网上部分的教程,主要讲述的是介绍控件.这并没有问题,但是没有把自己的使用经验也完整的描述出来. 所以特此编写此系列文章希望能帮助到,因为 ...

  8. Python数据可视化之Excel气泡图

    最终实现的效果如图: 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做案例的人,却不知道如何去学习更加高深的知识.那么针对这三类 ...

  9. windows版redis报错:本地计算机上的Redis服务启动后停止

    解决 1.如果需要临时启动Redis 使用命令:redis-server.exe   redis.windows.conf   --maxheap 200m 说明:200m是指定最大堆内存是200m, ...

  10. APM姿态控制流程

    对初学者了解控制流程有一定帮助 在主循环执行过程中(比如Pixhawk的任务调度周期2.5ms,400Hz:APM2.x为10ms,100Hz),每一个周期,程序会按下述步骤执行:• 首先,高层次文件 ...