倒數三天了~~~
今天的主題是介紹一些奇怪的C、C++語法。
眾所週知,要取得a陣列的第i格要寫a[i]
,但其實a[i]
是語法糖,他在編譯時會被解析成*(a+i)
來做判斷喔。
依據阿貝爾群 :a[i]
= *(a+i)
= *(i+a)
= i[a]
。
沒錯,其實在C跟C++的陣列,你就算寫i[a]
也是可以取得a陣列第i格的值喔!
-->
int n=10;
while(n-->0){
cout<<n<<endl;
}
只要使用「趨近於」運算子,就可以實現迴圈的時候每圈讓n慢慢的趨近於0喔!
才怪咧,其實並沒有這麼奇怪的運算子,他其實就是while(n-- >0)
喔。
只是每圈都執行一個n--
而已啦。
define是可以做到類似函式的設計喔,可以做到很簡單的範型的感覺
#define max(a,b) ((a)>(b)?(a):(b))
要注意小括弧要記得加,因為define是用展開的,如果不加的話,展開可能會形成語意問題。
在寫#define的時候,可以善用#這個酷酷的語法,他可以把他當成某種格式化字串的概念來使用,我不太會解釋,所以我們直接看程式碼吧!
#include<iostream>
using namespace std;
#define debug(x) cout<<#x<<":"<<x<<endl;
int main(){
int i = 10;
debug(i);
return 0;
}
這段程式碼的輸出結果是
i:10
#x的部分會被直接用debug()中的那個「i」給代替喔!
for(int i-0;i<n;i++){
cout<<a[i]<<" \n"[i==n-1];
}
這個前幾天的文章就已經出現了,但真的是很有趣的語法,很推薦大家學會。
C++有一個函式的修飾詞是constexpr,如果一開始傳入的就是常數,他可以在編譯時就進行運算。
constexpr unsigned int fib(int n)noexcept{
return ( n == 0 || n == 1 ? n : fib( n - 1 ) + fib( n - 2 ) );
}
假設呼叫時是 fib(13),他會直接在編譯時就算出答案,程式執行當下就可以O(1)喔!
(但其實要能被constexpr的函式要求還滿多的,像是不能有判斷式,要是一行句子之類的,所以使用前還是要去查一下用法,不是把你原本的函式加個constexpr就能解決。)
<=>
在C++中我們是可以重載類別的運算子的,但有時候在小於等於那邊總會寫的非常尷尬,因為邏輯幾乎差不多,很常會寫成這種東西。
class Obj{
public:
bool operator<(Obj o)const{
//實作小於判斷
}
bool operator!=(Obj o)const{
return *this<o || *this>o;
}
bool operator>(Obj o)const{return *this<o;}
bool operator<=(Obj o)const{return !(*this<o);}
bool operator>=(Obj o)const{return !(*this>o);}
bool operator==(Obj o)const{return !(*this!=o);}
};
看起來有點繁雜對吧。
在C++20,他提供了一個不是真正的運算子讓我們重載,可以把這些邏輯全部整理在一起。
class Obj{
public:
std::strong_ordering operator<=>(Obj o)const{
if(小於){
return -1;
}
else if(等於){
return 0;
}
else{
return 1;
}
}
};
你只要這樣寫,他就會自動幫你切出<、>、<=、>=、==、!=(請注意,他不是真正的運算子,你不能直接使用<=>來用,他只是幫助你一次宣告上述幾個運算子的語法糖而已)
這是一句酷酷的語法,利用xor的特性,可以做到沒有多餘變數的情況下,把兩個變數存的值交換(注意,需要是真的可以被xor運算的型態,比如int)。
他是
if{}
else {
if{}
else{}
}
因為裡面那組判斷算作一行
所以else的大括弧可以省略
變成
if{}
else
if{}
else{}
然後排版後變成
if{}
else if{}
else{}
然後就被當成一種語法來使用了
這些都是很有趣的語法,有些可能在其他語言上也有類似的實踐。
大家可以去玩玩看喔!
補充個,PHP 是內建航天飛機運算子的
https://www.php.net/manual/zh/language.operators.comparison.php
喔喔喔!原來如此