hotaruの蛍雪日記

競プロとゲームをしています

C言語を勉強しました

f:id:hotarunx:20201023014419p:plain

C言語完全に理解勉強しました。 今クオーターでC言語を使う講義を受けるので、勉強しなおしました。

C言語とは?

C言語プログラミング言語の1つ。 高級言語より速く低レベルな記述ができる。 C言語は他の言語よりはるかにたくさんの事例があるが、特に例を上げるならLinuxカーネルJava・CPythonがある。 C言語の機能を一通り列挙して感想を書く。

演算子

  • +,-,*,&は単項演算子である。単項演算子の存在を知らなかった。
  • 内容を変更できる式をlvalueという。
  • インクリメント演算子は適用対象がlvalueでなければならない。
  • 単項演算子二項演算子より優先度が高い。

浮動小数点数の定数は小数点以降を省略できる12.。知らなかった。 ゼロ拡張と符号拡張がある。

ブール

  • C言語では「真は0以外」。
  • ブール型として_Boolがある
  • stdbool.h.をインクルードするとbool型とtrue, falseキーワードを使える。

制御文

多重ループを抜ける方法としてフラグ変数・goto文がある。 一長一短というかどちらも微妙。 競プロではフラグ変数を使っている。

配列

  • 多次元配列で初期化子リストするとき、一番左以外に要素数を指定しないといけないint a[][2][4]
  • 多次元配列は配列のわかりやすい記法で、中身は配列。
  • 配列はメモリを確保するため宣言時に要素数が定まっていないといけない→一番左以外は要素数を指定する。
  • 多次元配列で初期化子リスト、全要素を並列させる方法int a[][2][4] = {1,2,3,4,5,6}があるのは知らなかった。

文字・文字列

  • やっぱ文字列型が無いのは面倒。
  • 文字列リテラルはメモリにリテラルの中身が確保されてそこへのポインタ。
  • 一部の文字を扱う関数はint型で処理する。EOFとかを扱うときに嬉しいのかな?
  • アスキー文字型が3つwchar_t, char16_t, char32_tもあることに困惑した。
  • ワイド文字をprintf("%lc\n", c);で出力しようとしたが、Cygwin環境以外では失敗した。
  • strcatのcatはconcatenationから来ている。

関数

関数定義の指定子はextern, staticがある。 staticを指定するstatic int func();と、関数は定義したソースファイルからのみ呼び出せる。

  • 関数定義の()の中はパラメータリストと言うらしい。
  • 関数プロトタイプ宣言はコンパイラが検証に使う。プロトタイプ宣言しないと検証がやばい。
  • 関数プロトタイプ宣言のパラメータリストにvoidを書くと、コンパイラが関数呼び出しのパラメータを検証する。
  • const修飾外しができる。やばい。

ポインタ

  • 配列名とポインタは少し違いがある。
  • 関数ポインタ型の例int (*)(int x, int y)
  • 関数ポインタ変数の宣言の例int (*func)(int x, int y)
  • 関数ポインタを覚えて自由度が上がったと感じたよ。

マクロ

  • あらゆる定数をマクロ化すると可読性が減少する。将来に渡って変化しない定数はマクロではなくてハードコードするのがグッドプラクティスだそうだ。
  • 関数的マクロはバグが怖い。

C標準IO

fgets,fscanf,fgetc,fputs,fprintf,fputcなどいろいろ関数がある。 EOFだったら中止するとかしないといけなくてファイルIOは面倒そう。

構造体(struct)

タグ名付きで定義したり、typedefで型名を与えると、構造体に名前を与えられる。 2つの違いは……?

  • フレキシブル配列メンバがある。
// タグ
struct pos {
    int x;
    int y;
};

// typedef
typedef struct {
    int x;
    int y;
} POS;

共用体(union)

同じ領域を複数の型で共有する。 ちょっと便利そう。

// 例 IDを整数か文字列で扱う
union id {
    int id_int;
    char id_str[10];
}

列挙型(enum

複数の整数型の定数をまとめて扱う。 ある整数がある状態を表すことにして、状態を整数で扱うときに便利そう。

// 例 学部卒、修士卒などを表す
enum grade {
    BACHELOR,
    MASTER,
    DOCTOR,
}

ビットフィールド

構造体のメンバが使うメモリをビット単位で指定できる。 例えば2ビットの整数をメンバにできる。 組み込みだと使うかもね(組み込みに興味がない)。

勉強を終えて

  • 関数ポインタ・ポインタ・共用体・列挙型・ビットフィールドは詳しく知らなかったので勉強になった。
  • まだポインタごりごり使ったプログラムを読む能力は無い。
  • Rust使いたいんだけどC言語でなければならないシチュエーションに出くわすかも。