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 的使用的更多相关文章

  1. 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'> ...

  2. python csv文件打开错误:_csv.Error: line contains NULL byte

    当python读取文件出现_csv.Error: line contains NULL byte时, # -*- coding:utf-8 -*- import csv with open(r'E:\ ...

  3. C语言学习笔记--#error 、 #line 和 #pragma 的使用

    1. #error 的用法 (1)#error 是一种预编译器指示字,用于生成一个编译错误消息 (2)用法:#error message //注意:message 不需要用双引号包围 (3)#erro ...

  4. 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 ...

  5. _csv.Error: line contains NULL byte

    原因是表格保存时扩展名为 xls,而我们将其改为csv文件通常是重命名: 解决方法只需把它另存为 csv 文件.

  6. Docker报错“Dockerfile parse error line 1: FROM requires either one or three arguments”

    看官方文档Format: 以 '#' 开头一行被视为评论,出现在其他位置视为参数. 也就不难理解报错原因:将写在同一行的注释视为参数了. 原Dockerfile: 改为:

  7. C 语言预处理

    在嵌入式系统编程中,不管是内核的驱动程序还是应用程序的编写,都涉及到大量的预处理与条件编译,这样做的好处主要体现在代码的移植性强以及代码的修改方便等特性,因此引入了预处理与条件编译的概念.在C语言的程 ...

  8. c语言编译预处理和条件编译执行过程的理解

    在C语言的程序中可包括各种以符号#开头的编译指令,这些指令称为预处理命令.预处理命令属于C语言编译器,而不是C语言的组成部分.通过预处理命令可扩展C语言程序设计的环境. 一.预处理的工作方式 1.1. ...

  9. C预编译, 预处理, C/C++头文件, 编译控制,

    在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作.#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的 ...

随机推荐

  1. [学习笔记] CS131 Computer Vision: Foundations and Applications:Lecture 2 颜色和数学基础

    大纲 what is color? The result of interaction between physical light in the environment and our visual ...

  2. 常用js方法封装

    常用js方法封装 var myJs = { /* * 格式化日期 * @param dt 日期对象 * @returns {string} 返回值是格式化的字符串日期 */ getDates: fun ...

  3. js 学习思维导图

  4. CF735E Ostap and Tree

    比较毒瘤的树形DP,子状态难想.这是主要是搬运一篇题解. 用\(f[i][j]\)表示\(i\)的子树中离\(i\)最近黑点的距离为\(j\),且距离超过\(j\)的点都被满足的方案数.转移时新建一个 ...

  5. 洛谷 P2932 [USACO09JAN]地震造成的破坏Earthquake Damage

    P2932 [USACO09JAN]地震造成的破坏Earthquake Damage 题目描述 Wisconsin has had an earthquake that has struck Farm ...

  6. EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER

    EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER ...

  7. Hadoop学习;測试;启动bug;secondary合并edits到fsimage

    一个Hadoop集群拥有多个并行的计算机.用以存储和处理大规模的数据集 Hadoop强调代码向数据迁移 要执行的程序在规模上比数据小的多,更easy移动,此外通过网络移动数据比载入执行程序更花时间,这 ...

  8. Hive分区表与分桶

    分区表 在Hive Select查询中.通常会扫描整个表内容,会消耗非常多时间做不是必需的工作. 分区表指的是在创建表时,指定partition的分区空间. 分区语法 create table tab ...

  9. shell文本过滤编程(一):grep和正則表達式

    [版权声明:转载请保留出处:blog.csdn.net/gentleliu.Mail:shallnew at 163 dot com] Linux系统中有非常多文件,比方配置文件.日志文件.用户文件等 ...

  10. m_Orchestrate learning system---二十、如何写代码不容易犯错

    m_Orchestrate learning system---二十.如何写代码不容易犯错 一.总结 一句话总结:能排序多排序 这次查错的启示: 1.代码数据更规整:要是取出的数据排序的话可以减少很多 ...