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__);
#line 1 "Test.c"
printf("%s:%d\n",__FILE__,__LINE__);
return ;
}
//--------------------------结束--------------------------

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()
{
printf("%s\n",VERSION);
return ;
}

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 = ;
//说明:因#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 ;
}

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)); //
printf("sizeof(Test2) = %d\n",sizeof(struct Test2)); //
return ;
}

(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));//
printf("sizeof(struct S2) = %d\n",sizeof(struct S2));//
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 ;
}

参考资料:
www.dt4sw.com
http://www.cnblogs.com/5iedu/category/804081.html

C语言学习笔记--#error 、 #line 和 #pragma 的使用的更多相关文章

  1. R语言学习笔记-Error in ts(x):对象不是矩阵问题解决

    1.问题 在对时间序列进行拟合操作时,发生:Error in ts(x):对象不是矩阵的错误,而直接在arima()函数中使用时没有问题的. > sample<-c2 > sampl ...

  2. GO语言学习笔记(一)

    GO语言学习笔记 1.数组切片slice:可动态增长的数组 2.错误处理流程关键字:defer panic recover 3.变量的初始化:以下效果一样 `var a int = 10` `var ...

  3. Go语言学习笔记(1)——顺序编程

    Go语言学习笔记这一堆主要是<Go语言编程>(人民邮电出版社)的读书笔记.中间会穿插一些零碎的点,比如源码学习之类的.大概就是这样吧. 1. 顺序编程 1.1 变量 变量的声明: var ...

  4. HTML语言学习笔记(会更新)

    # HTML语言学习笔记(会更新) 一个html文件是由一系列的元素和标签组成的. 标签: 1.<html></html> 表示该文件为超文本标记语言(HTML)编写的.成对出 ...

  5. 2017-04-21周C语言学习笔记

    C语言学习笔记:... --------------------------------- C语言学习笔记:学习程度的高低取决于.自学能力的高低.有的时候生活就是这样的.聪明的人有时候需要.用笨的方法 ...

  6. 2017-05-4-C语言学习笔记

    C语言学习笔记... ------------------------------------ Hello C语言:什么是程序:程序是指:完成某件事的既定方式和过程.计算机中的程序是指:为了让计算机执 ...

  7. Haskell语言学习笔记(88)语言扩展(1)

    ExistentialQuantification {-# LANGUAGE ExistentialQuantification #-} 存在类型专用的语言扩展 Haskell语言学习笔记(73)Ex ...

  8. Go语言学习笔记十三: Map集合

    Go语言学习笔记十三: Map集合 Map在每种语言中基本都有,Java中是属于集合类Map,其包括HashMap, TreeMap等.而Python语言直接就属于一种类型,写法上比Java还简单. ...

  9. Go语言学习笔记十二: 范围(Range)

    Go语言学习笔记十二: 范围(Range) rang这个关键字主要用来遍历数组,切片,通道或Map.在数组和切片中返回索引值,在Map中返回key. 这个特别像python的方式.不过写法上比较怪异使 ...

随机推荐

  1. alibaba的JSON.toString会把值为null的字段去掉,谨记

    alibaba的JSON.toString会把值为null的字段去掉,谨记 Map<String,Object> map = new HashMap<>(); map.put( ...

  2. Office文件的实质是什么

    Office文件的实质是什么 一.总结 一句话总结:对于一个Microsoft Office文件,其实质是一个Windows复合二进制文件(Windows Compound Binary File), ...

  3. 选择排序的php实现 Selection Sort

    选择排序Selection Sort的PHP实现,安全按照算法所写. 同一排序算法下,需要趟数最多的数列是什么数列呢?思考中. 每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序 ...

  4. 修复 Xcode 错误 “The identity used to sign the executable is no longer valid”

    如图: 解决方法来自:http://stackoverflow.com/questions/7088441/the-identity-used-to-sign-the-executable-is-no ...

  5. hzau 1205 Sequence Number(二分)

    G. Sequence Number In Linear algebra, we have learned the definition of inversion number: Assuming A ...

  6. jquery判断密码是否一致?

    密码 请输入密码 重新输入密码 请输入新密码 <input type="text" id="btn0"> 密码 <span class=&qu ...

  7. Django 基础 视图系统

    Django的View(视图) 一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应. 响应可以是一张网页的HTML内容,一个重定向,一个404错误, ...

  8. Thinkphp5.0 获取新增数据的ID

    // 方法1 insertGetId方法新增数据并返回主键值使用getLastInsID方法: Db::name('user')->insert($data); $userId = Db::na ...

  9. nyoj-1011-So Easy[II] (多边形面积求解)

    题目链接 /* Name:nyoj-1011-So Easy[II] Copyright: Author: Date: 2018/4/26 17:12:09 Description: 将多边形,从第一 ...

  10. SQL使用指南(2)—— 约束的使用

    主键约束 (1)创建表时添加主键约束 primary key<column_name> (2) 修改表时添加主键约束 ALTER TABLE table_name ADD CONSTRAI ...