C语言拾遗-C语言预处理-#error、#pragme与#line

本文将介绍几种预处理命令及其使用方法,其中包括 #line 命令、#error 命令和 #pragma 命令。此外,还讲述了_Pragma 运算符的相关知识。

定义行号

编译器会在警告消息、错误消息与调试信息中包含代码所在的行号与所在的源文件名,并提供给调试工具。你可以在源代码中利用 #line 命令改变编译器默认指定的文件名与行号信息。#line 命令的语法如下:

#line line_number ["filename"]

#line 命令的下一行行号会指定为 line_number。如果该命令也包含可选字符串字面量"filename",那么该编译器会把该字符串名称作为当前源文件名。

line_number 必须是大于 0 的十进制常量。如下例所示:

#line 1200 "primary.c"

包含 #line 命令的那一行代码,也可以包含其他宏。如果包含其他宏,预处理器会先展开所有宏,然后再执行 #line 命令。但要确保在宏展开后,#line 命令是正确的。

程序可以利用标准预定义宏 __LINE__ 和 __FILE__ 来访问当前的行号和文件名设置:

printf( "This message was printed by line %d in the file %s.\n",
        __LINE__, __FILE__ );

#line 命令通常用在将 C 源代码作为输出的程序上。通过将对应的输入文件行号放置在 #line 命令内,程序可以让 C 编译器的错误消息指向源文件中相应的行。

生成错误消息

无论是否有实际错误,#error 命令都会让预处理器发出错误消息。它的语法如下:

#error [text]

如果上述命令存在可选项 text,则 text 就会被包含在预处理器的错误消息中。然后,编译器会终止处理源代码,并结束执行,仿佛遇到了严重错误。text可以是任意预处理器记号序列。如果 text 中有其他宏,它们都不会被展开。最好在这里使用字符串字面量,以避免标点符号字符(如单引号)的影响。

下面的例子测试标准宏 __STDC__ 是否已经被定义。如果没有,则生成一个错误消息:

#ifndef __STDC__
  #error "This compiler does not conform to the ANSI C standard."
#endif

#pragma 命令

#pragma 命令是向编译器提供额外信息的标准方法,其格式如下:

#pragma [tokens]

如果 #pragma 之后的第一个标记(token)是 STDC,那么该命令就是一个标准 pragma。否则,该 #pragma 命令的作用取决于实现版本。为了保障代码的可移植性,应该尽量少使用 #pragma 命令。

如果预处理器支持所指定的标记,就会执行这些标记所代表的动作,或者把该信息传递给编译器。如果预处理器不支持所指定的标记,就忽略该 #pragma 命令。

例如,最新版本的 GNU C 编译器和微软 Visual C 编译器都支持 #pragma pack(n),它使得编译器让结构成员对齐到特定的字节边界。下面的例子使用 pack(1)指示每个结构成员必须对齐到字节边界:

#if defined( __GNUC__ ) || defined( _MSC_VER )
  #pragma pack(1)                             // 对齐字节,没有填充
#endif

单字节对齐方式可以确保结构成员之间不会有间隙。pack 的参数 n 通常是 2 的幂(但幂值较小)。例如,pack(2)把结构成员对齐到偶数地址,而 pack(4)把结构成员对齐到 4 为倍数的地址。pack()没有参数,它指示对齐方式设置为实现版本的默认值。

C99 新增下面三个标准的 pragma:

#pragma STDC FP_CONTRACT on_off_switch
#pragma STDC FENV_ACCESS on_off_switch
#pragma STDC CX_LIMITED_RANGE on_off_switch
on_off_switch 的值必须是 ON、OFF 或 DEFAULT。

如果检测到已经定义了 PI,则不再重复执行上述宏定义。该条件编译指令更重要的一个应用是防止头文件重复包含

_Pragma 运算符

无法通过宏展开创建一个 #pragma 命令(或任何其他命令)。当碰到需要这么做的情况时,C99 新增了一个预处理运算符 _Pragma,它可以与宏配合使用。它的语法如下:

_Pragma (string_literal )

_Pragma 运算符的工作方式是这样的。首先,该 string_literal 操作数会被“解字符串化”(destringized),或被转换为预处理器记号序列,该过程如下:删除字符串前后的双引号;使用"替代 \";使用 \ 替代 \\。然后,预处理器会翻译前述结果序列的记号,类似于 #pragma 命令。

参考链接

  • http://c.biancheng.net/view/455.html
  • GB/T 15272-1994 (6.8.4-6)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值