#pragma GCC poison 的一个有趣特性

来源:互联网 发布:p2p网络借贷入罪 编辑:程序博客网 时间:2024/06/10 05:21

今天做程序设计的作业时又看见一题,让使用char*实现一个"String"类(与std::string相似),但是要求上传的String类的.cpp实现代码却没有禁用string,导致一些函数直接可以先转换为string对象,用string提供的函数实现以后再转换回char*……然后就想应该可以用#pragma GCC poison来实现禁用string,但是同时也想到,因为#define和#pragma GCC poison都是预处理器来处理的,会不会使用#define能实现绕过#pragma GCC poison呢?实验表明在一些情况下是可以的,如下面两段代码

#include<iostream>#pragma GCC poison string#define youknow stringint main() {    std::youknow str;    return 0;}

#include<iostream>#define youknow string#pragma GCC poison stringint main() {    std::youknow str;    return 0;}

差别仅仅在于互换了#pragma GCC poison与#define,真是奇怪……一搜索,发现原来这是#pragma GCC poison的一个特性

在http://gcc.gnu.org/onlinedocs/gcc-3.2/cpp/Pragmas.html里是这么说的

If a poisoned identifier appears as part of the expansion of a macrowhich was defined before the identifier was poisoned, it willnotcause an error. This lets you poison an identifier without worryingabout system headers defining macros that use it.

如果被“染毒”的标识符在被“染毒”之前作为宏定义出现,那么它就不会造成error。后面的解释能看懂但不能理解……(头文件会用宏来定义标识符吗?)先放着

于是我又改了一下,变成这样

#pragma GCC poison string#include<iostream>#define youknow stringint main() {    std::youknow str;    return 0;}

一编译马上就扑街了,首当其冲的是stringfwd.h

又看了下stringfwd.h,发现有一行(37行)#pragma GCC system_header,感觉这应该就是之前所说的system header了,于是去看了http://gcc.gnu.org/onlinedocs/gcc-3.2/cpp/System-Headers.html#System%20Headers,又试了一下自己写的头文件

// GCC pragma teststd::string test;

#include<iostream>#define youknow string#include"test.h"#pragma GCC poison stringint main() {    std::youknow str;    return 0;}
本来想着头文件里面要加#pragma GCC system_header才不会报错,结果顺利编译,看来这个特性所要保护的system header不是指#pragma GCC system_header所声明的那种,感觉有点误导。

而且连这也能成功编译

#include<iostream>#define youknow stringstd::string test;#pragma GCC poison stringint main() {    std::youknow str;    return 0;}
这根本不是macro expansion,只是一段很裸的语句好吗!……

说不定实际上只是出现在#pragma GCC poison以后的标识符才会报错难过

结论:#pragma GCC poison应该加在所include的系统头文件后面,且尽量靠前

预处理器好强大

我好菜

感觉不补一下C和C++的各种reference都不行啊

pragma的reference后面的内容都是一边写博文一边测试的,不信拉倒

话说写文章的这个过程好像对于探究有点促进作用

創用 CC 授權條款
本著作係採用創用 CC 姓名標示-非商業性 3.0 美國 授權條款授權.
0 0