1. 程式人生 > >#pragma GCC poison 的一個有趣特性

#pragma GCC poison 的一個有趣特性

今天做程式設計的作業時又看見一題,讓使用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 string

int main() {
    std::youknow str;
    return 0;
}

#include<iostream>
#define youknow string
#pragma GCC poison string

int main() {
    std::youknow str;
    return 0;
}

差別僅僅在於互換了#pragma GCC poison與#define,真是奇怪……一搜索,發現原來這是#pragma GCC poison的一個特性

If a poisoned identifier appears as part of the expansion of a macrowhich was defined before the identifier was poisoned, it willnot

cause 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 string

int main() {
    std::youknow str;
    return 0;
}

一編譯馬上就撲街了,首當其衝的是stringfwd.h
// GCC pragma test
std::string test;

#include<iostream>
#define youknow string
#include"test.h"
#pragma GCC poison string

int main() {
    std::youknow str;
    return 0;
}
本來想著標頭檔案裡面要加#pragma GCC system_header才不會報錯,結果順利編譯,看來這個特性所要保護的system header不是指#pragma GCC system_header所宣告的那種,感覺有點誤導。

而且連這也能成功編譯

#include<iostream>
#define youknow string
std::string test;
#pragma GCC poison string

int main() {
    std::youknow str;
    return 0;
}
這根本不是macro expansion,只是一段很裸的語句好嗎!……

說不定實際上只是出現在#pragma GCC poison以後的識別符號才會報錯難過

結論:#pragma GCC poison應該加在所include的系統標頭檔案後面,且儘量靠前

前處理器好強大

我好菜

感覺不補一下C和C++的各種reference都不行啊

pragma的reference後面的內容都是一邊寫博文一邊測試的,不信拉倒

話說寫文章的這個過程好像對於探究有點促進作用

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

相關推薦

#pragma GCC poison一個有趣特性

今天做程式設計的作業時又看見一題,讓使用char*實現一個"String"類(與std::string相似),但是要求上傳的String類的.cpp實現程式碼卻沒有禁用string,導致一些函式直接可以先轉換為string物件,用string提供的函式實現以後再轉換回cha

pragma GCC poison GCC編譯遮蔽不安全函式

收集不安全的c函式,使用預編譯屬性禁止這些函式在專案原始碼中使用1.poison.h#ifndef __POISON_H_ #define __POISON_H_ #ifdef __cplusplus extern "C"{ #endif /* __cplusplus */

三大關系數據庫字段值超長的一個有趣對比

ins works 關系 created mys 數據源 rec alt mapping 三大關系數據庫字段值超長的一個有趣對比 在開發中,我們可能會遇到插入字段值超長的情況,前陣子遇到這樣一個案例,結果一對比後發現一個有趣的現象,如果插入字段值超長,ORACLE、SQ

一個有趣的邏輯漏洞

情況 任務 有趣 提供商 很多 減少 一個 有趣的 做的 漏洞存在於一個外包服務提供商做的遊戲形式的內網系統。 其中,有一項功能為發布懸賞任務,金幣從自己現有金幣中扣。 這一處存在競爭條件,並發漏洞。 在短時間內發布 無數個 懸賞任務,因為競爭條件的存在,在金幣只有5個的情

#pragma GCC system_header用法

osi 手冊 mat clu because lin however director ebr 在看公司公共庫的頭文件中發現了:#pragma GCC system_header一行,以前沒有見過這種用法,在網上查了一下,解釋如下: 從#pragma GCC system

VID 與 PVID 的簡單概述,附上一個有趣案例

vlan PVID VID 重要前提,交換機內部的幀都是會打tag的 PVID:port-based vlan id pvid是交換機上的概念,說的是進入該端口的報文如果沒有打vlan id就按pvid的值打上 PVID是基於端口的VLAN ID,一個端口可以屬於多個vlan(trunk 口),

關於JAVA多線程的一個有趣的現象

有趣的 決定 sleep zed sync end AR 但是 執行 模擬一個售票系統,或者銀行取錢。 class 銀行{   synchronized getmoney(){     //這裏要sleep,為了延緩速度。   } } class 顧客 extend

HDU6438 Buy and Resell 解題報告(一個有趣的貪心問題的嚴格證明)

include 目前 users 更新 完全 計算 解題報告 tput 有一個 寫在前面 此題是一個很容易想到的貪心題目,但是正確性的證明是非常復雜的。然而,目前網上所有題解並未給出本題貪心算法的任何正確性證明,全部僅停留在描述出一個貪心算法。本著對算法與計算機科學的熱愛

一個有趣的小知識-church計數

style 小知識 知識 code lam pre pan bsp spa (define zero (lambda(f) (lambda(x)x))) (define (add-1 n) (lambda(f)(lambda(x)(f((n f)x))))

給18小萌新的一個有趣的小問題,取石子問題

題目描述: 現在地上橫著一排放了N堆石頭(N是偶數),每一堆石頭的個數不確定(但是總數和為奇數)。 然後兩個人輪流取石頭,規則是一次只能取一堆,而且只能取首位,最後誰拿到的石頭多誰取勝,請問如果你先手的話,你是否有一個必勝的策略? 題解: 答案當然是有的,那麼這個思路是怎麼樣的呢

Oracle DB 12.2(12cR2)的一個特性:硬解析失敗的SQL語句(需要符合一定條件)列印到alert_sid.log中.

How to Identify Hard Parse Failures (Doc ID 1353015.1)Bug 16945190 - Diagnostic enhancement to dump parse failure information automatically (Doc ID 1694519

Oracle DB 12.2(12cR2)的一個特性:硬解析失敗的SQL語句(需要符合一定條件)打印到alert_sid.log中.

erro p s doc oracl 12c ica oracle fail err How to Identify Hard Parse Failures (Doc ID 1353015.1)Bug 16945190 - Diagnostic enhancement to

一個有趣的足球賽推理題及本人的推理

以下是一場足球賽成績表: 場數:該隊總共比過的場數 勝 :該隊勝利的場數 敗 :該隊失敗的場數 平手:該隊平手的場數 進球:該隊在所有比賽中進球數總合 失球:該隊在所有比賽中讓對方進球數總合 積分:勝加2分,平手加1分,敗加0分 已知,下面這張成績表沒有一個數字是正確的

一個有趣的非同步時序邏輯電路設計例項 ——MFM調製模組設計筆記

本文從本人的163部落格搬遷至此。 MFM是改進型頻率調製的縮寫,其本質是一種非歸零碼,是用於磁介質硬碟儲存的一種調製方式。調製規則有兩句話,即兩個翻轉條件: 1、為1的碼元在每個碼元的正中進行一次翻轉;為0的碼元不翻轉。 2、對連續兩個為0的碼元,則在第一個為0的碼元結束時翻轉一次;單個的0碼元不翻轉

移動開發----biu,biu,一個有趣的EditText

BiuEditText biu,biu,一個有趣的EditText 直接看效果 and Usage Step 1 三個類: ONE(主VIEW): package me.james.biuedittext;

對於prim的一個有趣但有點奇怪的想法

prim演算法找最小生成樹適用於無向圖,對於有向加權圖會產生錯誤。 比如 1->2,8 1->3,8 2->3,4 3->2,3 最小生成樹1->2->3 而不是3->2; 這是因為2,3之間相互的邊在prim演算法中無法判斷,或者根本意識不到3-&g

bootstrap應用+一個有趣的css

前端學習網站:https://www.freecodecamp.org Bootstrap的使用 匯入boortstrap css檔案 eg: <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/boo

遇到一個有趣的邏輯漏洞

遇到個有趣的邏輯漏洞,和大家分享一下。  某系統資料庫是mysql。user表有個code欄位,型別是int(11),這個欄位是儲存一個隨機數,用來找回密碼的時候做驗證,預設值是0。  找回密碼時候的步驟是,首先填寫自己郵箱,接收重置密碼的郵件,點選連結,訪問如下程式

一個有趣的C程式碼

之前寫的一個小程式碼,但只在Windows下有效果: #include <stdio.h> #include <stdlib.h> #define decode(p,r,i,n,t,f) r##f##r##i##t##p #define puts d

一個有趣的小例子,帶你入門協程模組-asyncio

一個有趣的小例子,帶你入門協程模組-asyncio 上篇文章寫了關於yield from的用法,簡單的瞭解非同步模式,【https://www.cnblogs.com/c-x-a/p/10106031.html】這次讓我們通過一個有趣例子帶大家瞭解asyncio基本使用。 目標效果圖 基本