#error 、 #line 和 #pragma 的使用
1. #error 的用法
(1)#error 是一种预编译器指示字,用于生成一个编译错误消息
(2)用法:#error message //注意:message 不需要用双引号包围
(3)#error 编译指示字用于自定义程序员特有的编译错误消息。类似的,#warning 用于生成编译警告消息
(4)#error 可用于提示编译条件是否满足。编译过程中的任何错误意味着无法生成最终的可执行程序
2. #line 的用法
(1)#line 用于强制指定新的行号和编译文件名,并对源程序的代码重新编号
(2)用法:#line number newFilename //newFilename 可省略
(3)#line 编译指示字的本质是重定义__LINE__和__FILE__

- #include <stdio.h>
- //作者 A 写的代码
- //--------------------------开始--------------------------
- //把 line 的下一行定义为第 1 行,文件名为“a.c”
- #line 1 "a.c"
- //--------------------------结束--------------------------
- //作者 B 写的代码
- //--------------------------开始--------------------------
- //把 line 的下一行定义为第 1 行,文件名为“b.c”
- #line 1 "b.c"
- //--------------------------结束--------------------------
- //作者 C 写的代码
- //--------------------------开始--------------------------
- #line 1 "MyCode.c"
- int main(){
- printf("%s:%d\n",__FILE__,__LINE__);//输出 MyCode.c:4
- #line 1 "Test.c"
- printf("%s:%d\n",__FILE__,__LINE__);//输出 Test.c:1
- return 0;
- }
- //--------------------------结束--------------------------

3.#pragma 的使用
(1)#pragma 用于指示编译器完成一些特定的动作 (2)#pragma 所定义的很多指示字是编译器特有的,在不同的编译器间是不可移植的
①预处理器将忽略它不认识的#pragma 指令
②不同编译器可能以不同的方式解释同一条#pragma 指令
(3)一般用法:#pragma parameter //注意,不同的 parameter 参数语法和意义不同
3.1.#pragma message——用于自定义编译消息
(1)message 参数在大多数的编译器中都有相似的实现
(2)message 参数在编译时输出消息到编译输出窗口中
(3)message 用于条件编译可提示代码的版本信息
(4)与#error 和#warning 不同,#pragma message 仅仅代表一条编译消息,不代表程序错误

- #include <stdio.h>
- #if defined(ANDROID20)
- #pragma message("Complie Android SDK 2.0...")
- #define VERSION "Android 2.0"
- #elif defined(ANDROID23)
- #pragma message("Complie Android SDK 2.3...")
- #define VERSION "Android 2.3"
- #elif defined(ANDROID40)
- #pragma message("Complie Android SDK 4.0...")
- #define VERSION "Android 4.0"
- #else
- #error Compile Version is not provided!
- #endif
- int main()
- {
- //可用命令行编译:gcc 24-1.c -DANDROID40
- //在 gcc 下输出:
- // 24-1.c:10: note: #pragma message: Complie Android SDK
- 4.0...
- //在 vc\bcc 下输出: Complie Android SDK 4.0...
- printf("%s\n",VERSION);
- return 0;
- }

3.2.#pragma once——用于保证头文件只被编译一次
(1)#pragma once 用于保证头文件只被编译一次 (2)#pragma once 是编译器相关的,不一定被支持(vc\gcc 都支持,bcc 不支持!)
(3)#pragma once 比#ifndef…#define…#endif 效率高,因为后者定义的头文件仍然被处理。前者只要头文件被定义一次,就不会再次被处理。
global.h

- #pragma once
- int g_nValue = 1;
- //说明:因#pragma once 不被所有的编译器支持(如 bcc 不支持),但
- //#pragma once 又比#ifndef...#define...#endif 效率高,如果
- //为了让支持#pragma once 的编译器有更高的效率有更高的效率,可以采用如下的头文件定义方式/*
- #pragma once //当编译器不支持#pragma once 时,会直接忽略这行
- ifndef _HEADER_FILE_H_
- #define _HEADER_FILE_H_
- //source code
- #endif
- */

test.c

- #include <stdio.h>
- #include "global.h"
- #include "global.h" //被 include 两次
- int main()
- {
- printf("g_nValue = %d \n",g_nValue);
- return 0;
- }

3.3.#pragma pack——用于指定内存对齐方式
(1)什么是内存对齐
不同类型的数据在内存中按照一定的规则排列而不一定是顺序的一个接一个的排列。
结构体大小的计算

- #include <stdio.h>
- #pragma pack(2)
- struct Test1
- {
- char c1; //对齐参数:min(1,2)=1, offset = 0short s; //对齐参数: min(2,2)=2, offset = 2
- char c2; //对齐参数:min(1,2)=1, offset = 4
- int i; //对齐参数:min(4,2)=2, offset = 6
- };
- #pragma pack()
- #pragma pack(4)
- struct Test2
- {
- char c1; //对齐参数:min(1,4)=1, offset = 0
- char c2; //对齐参数:min(1,4)=1, offset = 1
- short s; //对齐参数:min(2,4)=2, offset = 2
- int i; //对齐参数:min(4,4)=4, offset = 4
- };
- #pragma pack()
- int main()
- {
- printf("sizeof(Test1) = %d\n",sizeof(struct Test1)); //10
- printf("sizeof(Test2) = %d\n",sizeof(struct Test2)); //8
- return 0;
- }

(2)为什么需要内存对齐?
CPU 对内存的读取不是连续的,而是分成块读取的,块的大小只能是 1、2、4、8、 16....字节,当读取操作的数据未对齐,则需要两次总线周期来访问内存,此性能会大打折扣 ,某些硬件平台只能从规定的相对地址处读取特定类型的数据,否则产生硬件异常
(3)#pragma pack(n)能够改变编译器的默认对齐方式(默认是按 4 字节对齐)
①struc 占用的内存大小
A.第一个成员起始于 0 偏移处
B.每个成员以 min(sizeof(成员的类型),n)的对齐参数进行对齐。即偏移地址必须 能被对齐参数整除,在复合结构体中,某个成员(结构体类型)的对齐参数为其内部长度最 大的数据成员的对齐参数作为这个成员的对齐参数。
②结构体总长度必须为所有对齐参数的整数倍。

- #include <stdio.h>
- #define OFFSET(st,member) ((int)&((struct st*)0)->member)
- #pragma pack(1)
- struct S1
- {
- short a;
- long b;//对齐参数:min(4,1)=1,sizeof(long)=4;->最大成员
- };
- #pragma pack()
- #pragma pack(2)
- struct S2
- {
- char c;//offset = 0;
- struct S1 d;//offset = 1(对齐参数为 min(1,2)),sizeof(s1)=6;
- double e;//offset = 8(对齐参数为 min(8,2))
- };
- #pragma pack()
- int main()
- {
- printf("sizeof(struct S1) = %d\n",sizeof(struct S1));//6
- printf("sizeof(struct S2) = %d\n",sizeof(struct S2));//16
- printf("Member's Offset of Struct S2:\n");
- printf("&s2.c=%d, &s2.d=%d, &s2.e=%d\n",
- OFFSET(S2,c),OFFSET(S2,d),OFFSET(S2,e));
- return 0;
- }

转自:
https://www.cnblogs.com/CoderTian/p/5903280.html
#error 、 #line 和 #pragma 的使用的更多相关文章
- error: <class 'xml.parsers.expat.ExpatError'>, syntax error: line 1, column 0: file: /usr/local/lib/python2.7/xmlrpclib.py line: 557
当linux设备上开启sonar6.2时, supervisorctl status报如下错误: error: <class 'xml.parsers.expat.ExpatError'> ...
- python csv文件打开错误:_csv.Error: line contains NULL byte
当python读取文件出现_csv.Error: line contains NULL byte时, # -*- coding:utf-8 -*- import csv with open(r'E:\ ...
- C语言学习笔记--#error 、 #line 和 #pragma 的使用
1. #error 的用法 (1)#error 是一种预编译器指示字,用于生成一个编译错误消息 (2)用法:#error message //注意:message 不需要用双引号包围 (3)#erro ...
- sass报 error (Line XX: Invalid GBK character "\xE4") 的解决办法
在webstorm配置的SASS,插入中文注释报错: cmd.exe /D /C call D:\ProgramFiles\Ruby24-x64\bin\sass.bat --no-cache --u ...
- _csv.Error: line contains NULL byte
原因是表格保存时扩展名为 xls,而我们将其改为csv文件通常是重命名: 解决方法只需把它另存为 csv 文件.
- Docker报错“Dockerfile parse error line 1: FROM requires either one or three arguments”
看官方文档Format: 以 '#' 开头一行被视为评论,出现在其他位置视为参数. 也就不难理解报错原因:将写在同一行的注释视为参数了. 原Dockerfile: 改为:
- C 语言预处理
在嵌入式系统编程中,不管是内核的驱动程序还是应用程序的编写,都涉及到大量的预处理与条件编译,这样做的好处主要体现在代码的移植性强以及代码的修改方便等特性,因此引入了预处理与条件编译的概念.在C语言的程 ...
- c语言编译预处理和条件编译执行过程的理解
在C语言的程序中可包括各种以符号#开头的编译指令,这些指令称为预处理命令.预处理命令属于C语言编译器,而不是C语言的组成部分.通过预处理命令可扩展C语言程序设计的环境. 一.预处理的工作方式 1.1. ...
- C预编译, 预处理, C/C++头文件, 编译控制,
在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作.#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的 ...
随机推荐
- vue自定义tap指令
1.Vue指令 Vue提供自定义实现指令的功能, 和组件类似,可以是全局指令和局部指令,详细可以参见vue官网自定义指令一节(https://cn.vuejs.org/v2/guide/custom- ...
- [Codeforces 626F]Group Projects
题目大意: 给定\(n\)个数\(a[1]\sim a[n]\),让你把它分为若干个集合,使每个集合内最大值与最小值的差的总和不超过\(K\).问总方案数. 解题思路: 一道很神的dp题. 首先将数进 ...
- BZOJ 3295 [CQOI2011]动态逆序对 (三维偏序CDQ+树状数组)
题目大意: 题面传送门 还是一道三维偏序题 每次操作都可以看成这样一个三元组 $<x,w,t>$ ,操作的位置,权值,修改时间 一开始的序列看成n次插入操作 我们先求出不删除时的逆序对总数 ...
- Python-基础-day6
1.二进制 前言:计算机一共就能做两件事:计算和通信 2.字符编码 生活中的数字要想让计算机理解就必须转换成二进制.十进制到二进制的转换只能解决计算机理解数字的问题,那么文字要怎么让计算机理解呢? 于 ...
- 使用xpath进行熟悉href属性
HTML文档 <html> <body> <a href="http://www.example.com">Example</a> ...
- 紫书 习题7-13 UVa 817(dfs+栈求表达式的值)
题目链接 点击打开链接 这道题分为两个部分, 一用搜索枚举每种可能, 二计算表达式的值, 有挺多细节需要注意 特别注意我的代码中在计算表达式的值中用到了一个!(代码枚举中的!表示不加符号, 我现在说 ...
- 【codeforces 733E】Sleep in Class
[题目链接]:http://codeforces.com/problemset/problem/733/E [题意] 有n级台阶,每个台阶上都有一个tag; 标记着向上或向下; 你到了某级台阶,就要按 ...
- 工具-VS使用GIT工具
由于VS中集成了GIT插件,本机安装了GIT工具和TortoiseGit工具,造成在VS中GIT无法同步,于是将TortoiseGit卸载,再次启用VS中的GIT插件,重新初始化GIT文件夹,问题解决 ...
- ASP.NET-DropDownListFor绑定model数据
在ASP.NET中,DropDownListFor绑定model数据比用html的select方便太多了,配合listmode这种模型集合就可以在controller里面直接foreach循环处理li ...
- java io包File类
1.java io包File类, Java.io.File(File用于管理文件或目录: 所属套件:java.io)1)File对象,你只需在代码层次创建File对象,而不必关心计算机上真正是否存在对 ...