😺
C言語 こんなことできるんだ集
はじめに
C言語に触れる中でこんな機能あったんだ!こんなことできるの!?と思ったものを集めました!
サンプルコードは簡略化しています
環境
以下の環境で動作を確認しました
- WSL2 Ubuntu 20.04.2 LTS
- gcc 9.3.0
配列の変数名と添え字の入れ替え
配列の変数名と添え字を入れ替えても正しく動く
int a[] = { 0, 1, 2 };
printf("%d", 1[a]); // 1
// a[1] と 1[a] は同じ
文字列に添え字を使う
文字列にも配列と同じように添え字を用いることができる
printf("%c", "aiueo"[3]); // e
#で文字列化
マクロの文字列化演算子#
を使って整数などを文字列にすることができる
#define TO_STRING(arg) #arg
char a[] = TO_STRING(42);
char b[] = TO_STRING(3.14);
printf("%s, %s", a, b); // 42, 3.14
##でトークンの連結
マクロのトークン連結演算子##
を使ってトークン(ソースコード上の名前)を連結できる
#define CAT(a, b) a##b
char s1[] = "foo";
char s2[] = "bar";
printf("%s, %s", CAT(s, 1), CAT(s, 2)); // foo, bar
// printf("%s, %s", s1, s2); と同じ
printfの%nで出力した文字数取得
printfの%n
というフォーマット指定子で%nが現れるまでに出力した文字数を変数に代入できる
int n;
printf("abcdefg%n", &n); // abcdefg
printf("%d", n); // 7
これを利用して Format String Attack という脆弱性への攻撃に使われるらしい
トリグラフ
詳細は次のリンクで
簡単に言うと #, [, { などの記号を ?? から始まる3文字で表すことができるHello world を出力するプログラム
??=include <stdio.h>
int main(void) ??<
printf("Hello world");
??>
gcc の場合、コンパイル時に -trigraphs
オプションをつける必要がある
main 関数なしで実行する
こちらも詳細は次のリンクから
Hello world を出力するプログラム
#include <stdio.h>
extern void _exit(register int);
int _start() {
printf("Hello world\n");
_exit(0);
}
gcc の場合、コンパイル時に -nostartfiles
オプションをつける必要がある
最後に
いくつ知っていましたか?
実用性はほとんどありませんが、知っていたら他の人に自慢できます!!
間違いや、他にもこれ追加してほしい!というのがあったら教えてください:)
Discussion