😺

C言語 こんなことできるんだ集

2021/09/02に公開

はじめに

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 という脆弱性への攻撃に使われるらしい

トリグラフ

詳細は次のリンクで
https://pknight.hatenablog.com/entry/20090818/1250598342
簡単に言うと #, [, { などの記号を ?? から始まる3文字で表すことができる

Hello world を出力するプログラム

??=include <stdio.h>

int main(void) ??<
    printf("Hello world");
??>

gcc の場合、コンパイル時に -trigraphs オプションをつける必要がある

main 関数なしで実行する

こちらも詳細は次のリンクから
https://jp.quora.com/C-のプログラムを-main-なしで書く事はできますか

Hello world を出力するプログラム

#include <stdio.h>

extern void _exit(register int);

int _start() {
    printf("Hello world\n");
    _exit(0);
}

gcc の場合、コンパイル時に -nostartfiles オプションをつける必要がある

最後に

いくつ知っていましたか?
実用性はほとんどありませんが、知っていたら他の人に自慢できます!!
間違いや、他にもこれ追加してほしい!というのがあったら教えてください:)

Discussion