网站建设报告书范文可以做动效的网站
网站建设报告书范文,可以做动效的网站,acf wordpress,网站建设明薇通网络文章目录 预定义宏_ _func_ _是C语言的预定义标识符 #line和#error#pragma泛型选择#xff08;C11#xff09;参考 预定义宏
C标准规定了一些预定义宏#xff1a;
_ _func_ _是C语言的预定义标识符
C99 标准提供一个名为_ _func_ _的预定义标识符#xff0c;它展开为一… 文章目录 预定义宏_ _func_ _是C语言的预定义标识符 #line和#error#pragma泛型选择C11参考 预定义宏
C标准规定了一些预定义宏
_ _func_ _是C语言的预定义标识符
C99 标准提供一个名为_ _func_ _的预定义标识符它展开为一个代表 函数名的字符串该函数包含该标识符。那么_ _func_ _必须具有函数 作用域而从本质上看宏具有文件作用域。因此_ _func_ _是C语言的预定 义标识符而不是预定义宏。
下面程序中使用了一些预定义宏和预定义标识符。注意其中一 些是C99 新增的所以不支持C99的编译器可能无法识别它们。如果使用 GCC必须设置-stdc99或-stdc11。
predef.c程序
// predef.c -- 预定义宏和预定义标识符
#include stdio.h
void why_me();
int main(){printf(The file is %s.\n, __FILE__);printf(The date is %s.\n, __DATE__);printf(The time is %s.\n, __TIME__);printf(The version is %ld.\n, __STDC_VERSION__);printf(This is line %d.\n, __LINE__);printf(This function is %s\n, __func__);why_me();return 0;
}
void why_me(){printf(This function is %s\n, __func__);printf(This is line %d.\n, __LINE__);
}下面是该程序的输出
The file is predef.c.
The date is Sep 23 2013.
The time is 22:01:09.
The version is 201112.
This is line 11.
This function is main
This function is why_me
This is line 21.#line和#error
#line指令重置_ _LINE_ _和_ _FILE_ _宏报告的行号和文件名。可以这 样使用#line
#line 1000 // 把当前行号重置为1000
#line 10 cool.c // 把行号重置为10把文件名重置为cool.c#error 指令让预处理器发出一条错误消息该消息包含指令中的文本。 如果可能的话编译过程应该中断。可以这样使用#error指令
#if _ _STDC_VERSION_ _ ! 201112L
#error Not C11
#endif编译以上代码生成后输出如下
$ gcc newish.c
newish.c:14:2: error: #error Not C11
$ gcc -stdc11 newish.c
$如果编译器只支持旧标准则会编译失败如果支持C11标准就能成 功编译。
#pragma
在现在的编译器中可以通过命令行参数或IDE菜单修改编译器的一些 设置。#pragma把编译器指令放入源代码中。例如在开发C99时标准被 称为C9X可以使用下面的编译指示pragma让编译器支持C9X
#pragma c9x on一般而言编译器都有自己的编译指示集。例如编译指示可能用于控 制分配给自动变量的内存量或者设置错误检查的严格程度或者启用非标 准语言特性等。C99 标准提供了 3 个标准编译指示。
C99还提供_Pragma预处理器运算符该运算符把字符串转换成普通的 编译指示。例如
_Pragma(nonstandardtreatmenttypeB on)等价于下面的指令
#pragma nonstandardtreatmenttypeB on由于该运算符不使用#符号所以可以把它作为宏展开的一部分
#define PRAGMA(X) _Pragma(#X)
#define LIMRG(X) PRAGMA(STDC CX_LIMITED_RANGE X)然后可以使用类似下面的代码
LIMRG ( ON )顺带一提下面的定义看上去没问题但实际上无法正常运行
#define LIMRG(X) _Pragma(STDC CX_LIMITED_RANGE #X)问题在于这行代码依赖字符串的串联功能而预处理过程完成之后才会 串联字符串。
_Pragma 运算符完成“解字符串”destringizing的工作即把字符串中 的转义序列转换成它所代表的字符。因此
_Pragma(use_bool \true \false)变成了
#pragma use_bool true false泛型选择C11
在程序设计中泛型编程generic programming指那些没有特定类 型但是一旦指定一种类型就可以转换成指定类型的代码。例如C在 模板中可以创建泛型算法然后编译器根据指定的类型自动使用实例化代 码。
C没有这种功能。然而C11新增了一种表达式叫作泛型选择表达式 generic selection expression可根据表达式的类型即表达式的类型是 int、double 还是其他类型选择一个值。泛型选择表达式不是预处理器指 令但是在一些泛型编程中它常用作#define宏定义的一部分。 下面是一个泛型选择表达式的示例
_Generic(x, int: 0, float: 1, double: 2, default: 3)_Generic是C11的关键字。_Generic后面的圆括号中包含多个用逗号分隔 的项。第1个项是一个表达式后面的每个项都由一个类型、一个冒号和一 个值组成如float: 1。第1个项的类型匹配哪个标签整个表达式的值是该 标签后面的值。例如假设上面表达式中x是int类型的变量x的类型匹配 int:标签那么整个表达式的值就是0。如果没有与类型匹配的标签表达式 的值就是default:标签后面的值。泛型选择语句与 switch 语句类似只是前 者用表达式的类型匹配标签而后者用表达式的值匹配标签。 下面是一个把泛型选择语句和宏定义组合的例子
#define MYTYPE(X) _Generic((X),\
int: int,\
float : float,\
double: double,\
default: other\
)宏必须定义为一条逻辑行但是可以用 \ 把一条逻辑行分隔成多条物理 行。
在这种情况下对泛型选择表达式求值得字符串。例如对 MYTYPE(5)求值得int因为值5的类型与int:标签匹配。
下面程序演示了这种用法
mytype.c程序
// mytype.c
#include stdio.h
#define MYTYPE(X) _Generic((X),\
int: int,\
float : float,\
double: double,\
default: other\
)
int main(void)
{
int d 5;
printf(%s\n, MYTYPE(d)); // d 是int类型
printf(%s\n, MYTYPE(2.0*d)); // 2.0 * d 是double类型
printf(%s\n, MYTYPE(3L)); // 3L是long类型
printf(%s\n, MYTYPE(d)); // d 的类型是 int *
return 0;
}下面是该程序的输出
int
double
other
otherMYTYPE()最后两个示例所用的类型与标签不匹配所以打印默认的字 符串。可以使用更多类型标签来扩展宏的能力但是该程序主要是为了演示 _Generic的基本工作原理。
对一个泛型选择表达式求值时程序不会先对第一个项求值它只确定 类型。只有匹配标签的类型后才会对表达式求值。
可以像使用独立类型“泛型”函数那样使用_Generic 定义宏。
参考
《C Primer Plus》
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/88350.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!